目录
1、使用场景
因为最近做一个国际化项目,在产品设计时候参考了一国外同行web网站。其中有一块内容需要涉及到可以整体给网站自定义样式,可以更改某个样式类的颜色属性。本人以前写过一段前端代码,针对css样式略懂;这个样式的颜色至少包含有两种类别的颜色:背景颜色(background-color)、字体颜色(color)。具体参照如下图所示:
2、实现思路与实现过程
2.1、业务场景实现描述
我们自己的实现还没有上图截图所示的实现那么复杂。上图是可以更新当前当定专题之中的样式内容,还可以在更改某个颜色后可以重新生成一个新的专题样式。我们的业务仅仅要求一个全局的default样式,然后是有一个自定义样式。选中默认样式或者自定义样式如果更改颜色。始终仅仅只更新自定义专题之中的对应的样式选择器对应的颜色。
2.2、实现此功能的解决思路
首先需要存储样式专题一张表(theme_ui_style),此表主要存储专题样式名称,以及专题样式对应的css文件。以及当前系统生效的那专题样式。
有个专题样式表,那肯定针对此专题,有对应可更改的样式选择器(selector)下可更改的颜色,颜色类型有分为前面提到的
背景颜色(background-color)、字体颜色(color)。于是需要在专题样式详情表之中需要区分不同选择器下的更改颜色类型。
同时本系统优势国际化的多语言。需要在设定选择器时候,进行国际化多语言翻译。此时需要在样式选择器中定义一占位符用于显示选择器信息的名称。具体设计如下表所示:
整个过 通过读取云端的网络文件到InputStream,通过针对css文件解析器CssParserUtil,替换需要更改颜色的样式选择器的颜色。然后把替换完毕后的css回写到云端。然后网页在刷新获取最新的css文件。
此处需要注意,为了避免web前端使用缓存需要每次存储的css文件名称不一样。
3、成果展现
目前替换的css样式颜色暂时存储在本地,如下图所示
4、总结
在参考下面所示的参考文章时候出现一个问题,所有的css文件的颜色值使用了是RGB格式了,经过排查和结合CSS Parser 解析jar文件里面的相关示例,sheet.getCssText(new CSSFormat().setRgbAsHex(true)) 最后结合示例实现实现了显示颜色为16进制的数据。最开始和同事讨论说可以使用读取行方式来操作css样式文件内容信息,最后仔细阅读后这个解决思路是可以解决json类文件,但是css样式比较特殊的无法使用同事提出的这种方式。
URL url = new URL("https://scorm-wd.oss-cn-beijing.aliyuncs.com/qxoss/ilms_themeui_css/10013/custom_theme.css");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
InputStream inStream = connection.getInputStream();
//InputStream inStream = new FileInputStream(new File("D://test.css"));
CSSStyleSheetImpl sheet = addOrUpdateRuleProperty(inStream,".hp-blueBtn","background-color","#2f77f1",null);
//CSSStyleSheet sheet = insertRule(inStream, ".div{width:100px;height:200px;}");
//CSSStyleSheet sheet = updateSelectorAllRuleText(inStream,".div","height:100px;");
//String cssRule = sheet.getCssRules().toString();
String cssRule =sheet.getCssText(new CSSFormat().setRgbAsHex(true));
System.out.println("cssRule:\n"+cssRule);
FileOutputStream out = new FileOutputStream("D://test1.css");
out.write(cssRule.getBytes());
out.close();
5、最新发现
因为项目使用了前端iView,于是很多内容使用的是Vue的前端框架,并且很多样式使用的是CSS3样式,发现CSS3有很多新选择特性如not选择等等。开始时候css3的样式选择器如果使用默认的CSSOMParser解析器,会最后CSS3丢掉。最后突然想到可能是css3的问题,经过排查本人引用的cssparser.jar包之中是否包含有css3解析器,同时网上搜索了参考文章 解析CSS3的参考文章 ,经过验证终于能够完整获得包含有css3的样式啦,终于舒了一口气问题圆满解决。
<dependency>
<groupId>net.sourceforge.cssparser</groupId>
<artifactId>cssparser</artifactId>
<version>0.9.27</version>
</dependency>
如下所示的选择器:
.hp-mainList .ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):hover, .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu):hover { background-color: #2f77f1 }
如果使用默认样式解析器:
//解析其他版本
final CSSOMParser parser = new CSSOMParser();
//能够解析css3
final CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
6、参考文章
java解析css文件工具类CssParserUtil.java
解析CSS3的参考文章 之中如下代码
private void init() {
if (style != null) {
String styleContent = style.getValue().getText();
if (styleContent != null && !styleContent.isEmpty()) {
InputSource source = new InputSource(new StringReader(styleContent));
CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
parser.setErrorHandler(new ParserErrorHandler());
try {
styleSheet = parser.parseStyleSheet(source, null, null);
cssFormat = new CSSFormat().setRgbAsHex(true);
CSSRuleList rules = styleSheet.getCssRules();
for (int i = 0; i < rules.getLength(); i++) {
final CSSRule rule = rules.item(i);
if (rule instanceof CSSStyleRuleImpl) {
styleRuleMap.put(((CSSStyleRuleImpl) rule).getSelectorText(), (CSSStyleRuleImpl) rule);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}