JavaScript中快速重新绘制Unicode符号数组

8
我希望更改具有相同CSS类的许多符号的背景/前景颜色。目前,我是用jQuery实现的,例如$('back_COLORED').css('background-color', '#00FF00'),但是当具有这样的类的元素很多(>900)时,这种方法很
似乎是因为jQuery不直接更改CSS规则,而是逐个查找所有元素并将内联样式应用于它们。至少,在检查器中看到的是这样。因此,问题是:
  • 如何更改CSS规则本身?
  • 速度会快得多吗?
  • 能否使其跨浏览器(IE6不算)?
更新:我正在尝试制作某种颜色方案编辑器。源代码位于http://github.com/kurokikaze/cinnabar/。不要在意PHP事情,编辑器完全是客户端(只使用从网络获取的一些库)。

更新2: 尝试使用canvas,仍然很慢。Canvas分支在http://github.com/kurokikaze/cinnabar/tree/canvas


1
我没有直接回答你的CSS问题,但是顺便说一下,按id或标签选择比按CSS类名选择要快得多,也许这是你可以探索以提高性能的一个途径。 - tbreffni
我试图通过选择父div的id来限制搜索范围。这有所帮助,但速度仍然很慢。我不知道如何使用不同的ID或标签来代替类。 - Kuroki Kaze
8个回答

3

覆盖类定义的最跨浏览器友好的方法是编写一个新规则并将其添加到文档中最后一个样式表的末尾。您可以编辑现有的样式规则,但即使是一些较新的浏览器也可能会使它变得困难。

function newRule(selector, csstext){
 var SS= document.styleSheets, S= SS[SS.length-1];
 // this example assumes at least one style or link element
 if(S.rules){
  S.addRule(selector,csstext,S.rules.length);
 }
 else if(S.cssRules){
  S.insertRule(selector+'{'+csstext+'}'),S.cssRules.length)
 }
}

newRule('.someclass','background-color:#0f0');

你可以在csstext中添加任意多个“property:value;”位。记得在类名前加上“.”或在id前加上“#”,并且CSS必须写成样式规则(使用连字符而不是驼峰命名法)。
当然,它不会覆盖内联样式,并且对于小的本地更改来说可能有些过度。它还可能使页面重绘比逐个更改元素更明显,但这可能正是你需要的。

2

根据不同的浏览器,处理方式也有所不同。这在Quirks Mode中有详细的记录。

一些库提供了抽象层,例如YUI的StyleSheet实用程序

使用预定义样式应该会显著提高性能,因为您不需要使用JS / DOM来循环遍历所有元素。

另一种方法是预定义您的样式:

body.foo .myElements { … }

然后编辑document.body.className


我正在使用颜色选择器在CSS中更改颜色。切换类不会有帮助。 - Kuroki Kaze
我想我曾经遵循过 Quirks Mode 文档,发现该技术会导致我正在测试的 IE6 版本崩溃。当然这不是什么坏事 ;) 但我只是想知道是否还有其他人见过这种情况? - Richard JP Le Guen
@Kuroki - 那就使用第一种技术吧 :) 如果你只有少量不同的情况,classes选项是一个简单的解决方案,更好地维护关注点分离。 - Quentin
有点奇怪,YUI的方法可以用,但是很慢(在Chrome中测试)。我需要测试其他浏览器。 - Kuroki Kaze

1

在更改要素之前将其隐藏起来,进行更改,然后再显示它们。这是一种常见的做法,可以加快速度,因为它可以最小化视口中的重新绘制事件。在这种情况下,当你只设置一个css属性时,可能不会有多大的好处,但还是值得一试。

尝试吧:

$('back_COLORED').hide();
$('back_COLORED').css('background-color', '#00FF00');
$('back_COLORED').show();

或者

$('back_COLORED').hide().css('background-color', '#00FF00').show();

我没有看到速度上有太大的差异。 - Kuroki Kaze

1

如果您可以通过id选择父div,也许您可以在其中选择标签?或者在父元素内部有相同类型的元素应该更改颜色和不应该更改颜色的元素吗?

能够了解您正在构建什么将是很好的。900多个对象似乎很多...也许可以使用完全不同的方法?Canvas、SVG?


这是一种颜色方案编辑器。源代码位于http://github.com/kurokikaze/cinnabar/。相关文件为index.html和css/style.css。 - Kuroki Kaze
我自己还没有使用过画布,但当人们认为Javascript很慢时,通常是DOM很慢,而不是JS。Canvas消除了DOM,所以我猜是可以的。当然,canvas的缺点是浏览器兼容性。毕竟这是HTML5...请查看http://html5demos.com/获取一些简单的画布示例。 - Adrian Schmidt
嗯...我下载了你的源代码,在FF3.6中运行它们都非常快。使用画布的那个在转换时更加流畅,但另一个对我来说也很不错。你遇到了哪些浏览器问题? - Adrian Schmidt
Chrome 4.0.249.89 dev和Firefox 3.5.8。当我尝试在HEAD上更改浅红色或任何画布上的颜色时,我可以看到滞后。也许这个电脑太卡了? :) - Kuroki Kaze
我会在家里的电脑上检查,那台电脑速度更快。如果问题是电脑引起的,你将得到赏金 :) - Kuroki Kaze
显示剩余2条评论

1

我建议尝试更改CSS属性,而不是解析DOM。
这里涉及到CSS引擎与DOM+JS的比较,胜者显然。

恰好我刚刚上传了一个用Javascript替换CSS的小型库:jstyle

这可能有些过度,但您会在jstyle.js的源代码中找到所有需要跨浏览器更新页面CSS属性的代码。


0

我认为更好的解决方案是编写一个更具体的CSS规则(可以覆盖正常颜色),并且可以通过更改一个元素的CSS类来激活。

例如,如果您有以下结构标记:

<div id="container">
    <span class="colored">Test 1</span>
    <span class="colored">Test 2</span>
</div>

还有 CSS :-

.colored { background-color: red; }
.newcolor .colored { background-color: blue; }

然后在你的jQuery中,将.newcolor类添加到容器div中:

$('#container').addClass('.newcolor');

当你这样做的时候,第二个CSS规则会覆盖第一个,因为它更具体。

通过从颜色选择器获取RGB值,JavaScript创建了新的CSS规则。 - Kuroki Kaze
嗯,我认为你可能很难找到完全基于JavaScript的解决方案。如果这是因为某种用户偏好设置的原因,你最好允许用户在一个更小的页面上选择颜色,然后使用CGI/asp或其他方式生成一个自定义的CSS文件,而不是通过JavaScript改变页面的颜色。 - U62

0
将 css 代码注入到 style 标签中:
var style = $('style').attr({
    type:"text/css",
    media:"screen",
    id:'changeStyle'
}).html('.tempClass { color:red } .tempClass p { background:blue }').prependTo('body');

对于你使用的颜色选择器所做的每个更改,只需重新编写#changeStyle标签内部的HTML内容。

不确定是否可行(未测试),但你应该尝试一下。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接