65.9K
CodeProject 正在变化。 阅读更多。
Home

基于 SVG 的星级评分控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.68/5 (11投票s)

2012年4月20日

GPL3

5分钟阅读

viewsIcon

28859

downloadIcon

456

一个使用 SVG 而不是图像精灵的星级评分控件

引言

星级评分控件在当今的网站上非常常见且无处不在。您可以在 amazon.com、netflix.com 甚至 codeproject.com 等网站上找到它们。这些控件允许用户对亚马逊上的商品、Netflix 上的电影,或者在 codeproject 的情况下对您目前正在阅读的文章进行评分。您是否想过它们是如何工作的?它们大多数是基于图像精灵和一些 CSS 神技。在您喜欢的搜索引擎中搜索一下,您就会明白我的意思。我认为现在是时候转向使用 SVG 而不是图像精灵的控件了。如今大多数常用的浏览器都完全支持 SVG。如果您的浏览器不支持,那您还在用它吗?基于 SVG 的控件有什么优势?如本文所示,基于 SVG 的控件可以高度可配置。您想要 5 颗星还是 10 颗星?您想让星星显示为黄色还是红色?我将在本文中介绍的 SVG 控件允许您轻松配置这些设置,并根据您的需求自定义控件。

背景

读者最好对 JavaScript、HTML 和 SVG 有一些基本的了解。我已在 IE9 和 Chrome 上测试了示例。

Using the Code

我们直接开始吧。下载 star_rating_demo.zip 并解压缩,您应该会在解压缩的文件夹中看到四个文件:star_rating.jsdemo.htmldemo2.htmldemo3.html

控件的所有代码都在一个文件 star_rating.js 中。我将通过 3 个示例来说明如何使用该控件。

示例 #1 demo.html

此示例的所有代码都在文件 demo.html 中,并在此处复制

<!doctype html>
<html>
<head>
</head>
<body>
    <div id="my_widget"
        class="rating_widget" 
        number_of_stars="5"
        initial_value="0"
        default_color="#ccc"
        initial_value_color="#ff0"
        final_value_color="#f00"
        captions="Poor, Didn't like it, OK, Good, Excellent!"
        onclick="clickHandler"
    ></div>
<script src="star_rating.js">    
</script>
<script>
    function clickHandler(sender, args)
    {
        alert('your rating: ' + args);
    }    
</script>
</body>
</html>   

由于技术限制,本文无法展示可运行的示例。将提供截图。要查看可运行的示例,只需访问 页面。

在网页浏览器中查看 demo.html 的截图

要查看完整的可运行示例及其功能,请在网页浏览器中打开 demo.html。您将看到 5 颗灰色星星(请查找上面的代码中的 default_color="#ccc")。当您将鼠标悬停在星星上时,它们会变成红色(请查找上面的代码中的 final_value_color="#f00"),并且还会显示相应的文本(差、不喜欢、一般、好、优秀!)。如果您单击,控件将冻结,并且 clickHandler 函数将被调用。评分将作为 args 参数传递给函数。查找应用于 div 的 class="rating_widget" - 这将导致控件出现在 div 中。

示例 #2 demo2.html

在此示例中,我们希望控件最初显示 10 颗星,并且初始评分为 7。此外,我将展示创建控件的另一种方法(这次是在 JavaScript 中,而不是像示例 #1 那样在标记中)

<!doctype html> 
<html> 
<head>
</head>
<body>    
<script src="star_rating.js">    
</script>
<script>
    var widget = new rating_widget(
    {
        number_of_stars: 10, // the total number of stars in the control
        initial_value: 7,    // initial rating
        default_color: 'rgb(200,200,200)',     // the grey stars 
        initial_value_color: 'rgb(255,255,0)', // the yellow stars
        final_value_color: 'rgb(255,0,0)',     // the red stars
        captions: '1,2,3,4,5,6,7,8,9,10',      // text to display to provide feedback to user                
        parentNode: document.body,   // parent node of the control
        onclick: function(sender, args)  // function to execute on mouse click
        { 
            alert('your rating: ' + args);
        }
    });            
</script>
</body>
</html>

在网页浏览器中查看 demo2.html 的截图

通过更改 rating_widget 构造函数的输入参数值,您可以根据您的需求配置控件 - 轻松更改颜色、星星数量和标题。

示例 #3 demo 3.html

在最后一个示例中,我们将显示一个静态控件 - 一个不允许用户更改评分的控件

<!doctype html>
<html>
<head>
</head>
<body>
    <div id="my_widget"
        class="rating_widget" 
        number_of_stars="5"
        initial_value="3.5"
        default_color="#ccc"
        initial_value_color="#ff0"
        final_value_color="#f00"        
        disabled="true"
    ></div>
<script src="star_rating.js">    
</script>
</body>
</html>

在网页浏览器中查看 demo3.html 的截图

disabled="true" 设置为 true 可以禁用控件,使其无法更改评分。

工作原理

现在让我们了解控件的内部工作原理。让我们从 star_rating.js 中的这段代码开始

document.body.onload = function()
{
    var array = document.getElementsByClassName('rating_widget');
    for(var i = 0; i < array.length; i++)
    {
        var e = array[i];
        var widget = new rating_widget(
        {
            number_of_stars: e.getAttribute('number_of_stars') ? e.getAttribute('number_of_stars') : 5,
            initial_value: e.getAttribute('initial_value') ? e.getAttribute('initial_value') : 0,
            default_color: parseColor(e.getAttribute('default_color'), 'rgb(200,200,200)'),
            initial_value_color: parseColor(e.getAttribute('initial_value_color'), 'rgb(255,255,0)'),
            final_value_color: parseColor(e.getAttribute('final_value_color'), 'rgb(255,0,0)'),
            captions: e.getAttribute('captions'),
            captions_class_name: e.getAttribute('captions_class_name'),
            onclick: e.getAttribute('onclick'),
            disabled: e.getAttribute('disabled'),
            parentNode: e
        });
    }
};

上面的函数将在 html 文档的 body 加载时执行。我们获取 html 文档中所有应用了 rating_widget 类的元素,并将它们存储在变量 array 中。然后我们遍历这些元素,并为每个元素创建一个星级评分控件。星星的数量默认为 5,除非元素上存在 number_of_stars 属性来定义您想要的控件中的星星数量。initial_value 是您想应用于控件的初始评分。对于从未评级过的项目,这将是 0,但对于反映过去的评级,则可以是非零值。与控件交互以了解 default_colorinitial_value_colorfinal_value_color 的含义。captions 是与不同评分对应的字符串数组。您可以通过 CSS 样式化字幕的外观,并在变量 captions_class_name 中传入 CSS 类名。onclick 定义了用户单击控件时要调用的函数。如果将 disabled 设置为 true,则控件将被禁用,意味着它会失去交互性并冻结。这在您想使用控件显示评分但又不允许用户更改评分时很有用 - 例如,如果用户未登录。控件的父节点通过 parentNode: e 指定。

现在让我们深入研究 rating_widget 函数。有趣的部分在 rating_widget 中的以下代码

for(var i = 0; i < n; i++)
{
    var star = document.createElementNS(svgns, "path");
    star.setAttributeNS(null, "d", coordinates);
    star.setAttributeNS(null, "transform", transform(0.3947432, 0, 0, 0.414816, 20*i, 1.159472));
    star.setAttributeNS(null, "style", style);
    svg_root.appendChild(star);
    var box = bbox(star);
    if (!disabled)
    {
        if (box) {    attachEventHandlers(box, boxes);    }
        else     {    attachEventHandlers(star, stars);    }
    }
    stars.push(star);
    boxes.push(box);
}
initial_state();

n 是我们要显示的星星数量。绘制一颗星的 SVG 路径存储在变量 coordinates 中。要绘制多颗星,我们重复使用相同的 coordinates,但对其应用转换。20*i 是转换的 x 分量,是关键部分。线粗、线型 - 是实线还是虚线等 - 在变量 style 中定义。bbox 函数计算星星的边界框。如果计算成功,我们会将鼠标事件处理程序附加到星星的边界框上,否则我们将处理程序附加到星星本身。有关更多详细信息,请参阅 帖子。鼠标事件处理程序为控件提供了交互性。initial_state 函数使用构造函数中传入的 initial_value 初始化控件。

在调试器中逐步执行代码,以更深入地了解其工作原理。

结论

在本文中,我介绍了一个使用 SVG 而非图像精灵和 CSS 的星级评分控件。该控件高度可配置,可以轻松更改星星的数量、颜色和标题文本。控件可以嵌入到 HTML 标记中(示例 #1 和 #3),或者可以通过 JavaScript 动态实例化(示例 #2)。希望对某些人有所帮助。

历史

  • 2012/4/20 - 初始帖子。
© . All rights reserved.