Download Source Files
View Live DemoA live demo is available for this Tutorial. Click here to view it online
Today we will be creating a dynamic dashboard with live charts, through the power ofChartJS. ChartJS is a powerful, dependency free JavaScript library which builds graphs via the canvas element. Best of all, it's easy for designers to get up and running. We'll be focusing on the pieces of the library that get you up and running with beautiful and functional charts fast. We will build a mobile-friendly dashboard from start to finish.
译者信息
下载源码
在线Demo在线演示请点击这里。
今天我们将会用ChartJS来创建一个动态仪表盘。ChartJS是一个强大、无依赖的JavaScript库,通过canvas元素来创建图表。最重要的是设计人员可以自己轻松的创建和运行图表。我们将会专注于库中能够让你快速创建美观、功能强大的图表的部分,从头到尾创建一个移动友好的动态仪表盘。
Getting Started
We're going to build our dashboard on top of HTML5 Boilerplate. Download the zip file, or clone the repository via Git. We're going to name our project directory "chartjs_dashboard", and drop all of the files directly there.
2 |
git clone git@github.com:h5bp/html5-boilerplate.git chartjs_dashboard |
Next, we'll grab ChartJS. Go to the uminified version at raw.github.com/nnnick/Chart.js/master/Chart.js, and copy the contents into your js/plugins.js file. Having the unminified version will make errors more readable if you run into them.
Tip: in production, you would use the minified version of the JavaScript, to make the dashboard more performant.
Your file structure should look like this:
13 |
│ ├── jquery-1.10.1.min.js |
14 |
│ └── modernizr-2.6.2.min.js |
Note: this does not include some of the files included in H5BP that we won't be using.
译者信息
开始
我们将用HTML5 Boilerplate模版项目来创建一个仪表盘。从github上直接将这个项目迁至chartjs_dashboard文件夹下:
2 |
git clone git@github.com:h5bp/html5-boilerplate.git chartjs_dashboard |
然后,我们需要去下载ChatJS。从raw.github.com/nnnick/Chart.js/master/Chart.js 下载没有压缩过的Chart.js, 将文件中的内容拷贝到 js/plugins.js中。如果你用了压缩版本的chart.js,由于可读性不高将会产生很多错误。
建议: 产品发布时你应该用压缩版本的Chart.js,这样仪表盘的性能将会更好。
项目文件结构如下:
13 |
│ ├── jquery-1.10.1.min.js |
14 |
│ └── modernizr-2.6.2.min.js |
注意: 这里的文件结构没有将H5BP中没有用到的文件包含进来。
Color Palette
Before we get into the coding of the site, let's start by setting up a color palette that we will use throughout the design. By doing this, we can establish a future "style guide" of sorts; this is a common practice for basically any given design.
If you are building the dashboard with a particular brand in mind, start by using the brand's colors. Today, we will define two main colors and two ancillary colors. We will also use shades or faded out versions of these colors.
- dark blue:#637b85
- green:#2c9c69
- yellow:#dbba34
- red:#c62f29
We will also use a lighter shade of the dark blue,#d0dde3. Lastly, we will be utilizing grayscale colors.
译者信息
调色板
在我们编写网站代码之前,我们先做一个调色板,这个调色板将贯穿后面整个设计之中。为了实现这个目标,我们可以建立一个如“风格向导”的东西,这个“向导”可以应用在任何设计之中。如果你想基于某种品牌来创建仪表盘,那咱就用这个品牌的颜色作为仪表盘的颜色。现在,我将定义两种主要颜色和两种辅助颜色,也许会用到比这些颜色深些或是浅些的颜色:
-
蓝黑:#637b85
-
绿色:#2c9c69
-
黄色:#dbba34
-
红色:#c62f29
我们也会用到深蓝或浅蓝,#d0dde3.最后我们也会用到灰度颜色。
ChartJS Basics
ChartJS uses the canvas element. The canvas element provides a JavaScript-only interface to draw pixels to a given rectangle area. It is often compared toSVG, which offers a DOM node based solution to creating vector graphics in the browser. However, pixels drawn to the canvas element are not kept in memory and thus don't respond to JavaScript events.
But enough with the tech talk - how do we get started quickly with ChartJS?
Luckily, the ChartJS homepage has plenty of examples to get us started quickly. The basic pattern is to create the canvas element in HTML, select it with JavaScript, and create the Chart while passing in the data the chart is built from.
1 |
< canvas id = "something" ></ canvas >
|
3 |
var canvas = document.getElementById("something"); |
4 |
var ctx = canvas.getContext("2d"); |
5 |
new Chart(ctx).Line(data, options); |
The above example would assume that you had defined `data` and `options` as objects, and would produce a line graph accordingly.
In our example, we will use the Doughnut graph, the Line graph, and the Radar graph. These graphs will represent different business-oriented metrics, but of course you can take this and adapt it to your needs.
译者信息
ChartJS 基础
ChatJS 用的是canvas(HTML5,译者注)元素.Canvas提供的是JavaScript接口,并能在指定的矩形区域来画像素。人们经常拿它和SVG(另一种矢量图形标准,译者注),SVG在浏览器中以DOM节点的形式来创建矢量图形的。但是,用canvas画的图不会留在内存中,而且也不会响应JavaScript事件。
废话少说,那怎样用CharJS来快速画图呢?很幸运,CharJS主页有很多例子。创建canvas基本的形式是用JavaScript创建,并在创建时传入要画图的数据。
1 |
<canvas id= "something" ></canvas>
|
3 |
var canvas = document.getElementById( "something" );
|
4 |
var ctx = canvas.getContext( "2d" );
|
5 |
new Chart(ctx).Line(data, options);
|
上面的例子是假设你已经定义了‘data’和‘option’对象了,并最终创建了一条线。在我们的例子中,我们将用到圆环圈图,线条和雷达图。这些图代表不同的商业指标,但你可以根据你的需要进行改变
Page Markup
Let's start by defining some basic HTML for the layout of our page.
03 |
< div class = "container clearfix" >
|
04 |
< h1 >Overview < span >July 8-12, 2013</ span >< a class = "button" >Change Date Range</ a ></ h1 >
|
07 |
< div class = "container clearfix" >
|
08 |
< div class = "third widget doughnut" >
|
09 |
< h3 >Breakdown of Hours</ h3 >
|
10 |
< div class = "canvas-container" >
|
11 |
< canvas id = "hours" ></ canvas >
|
14 |
< div class = "third widget line" >
|
15 |
< div class = "chart-legend" >
|
16 |
< h3 >Shipments per Day</ h3 >
|
18 |
< div class = "canvas-container" >
|
19 |
< canvas id = "shipments" ></ canvas >
|
22 |
< div class = "third widget" >
|
23 |
< div class = "chart-legend" >
|
24 |
< h3 >Customer Service Assessment</ h3 >
|
26 |
< div class = "canvas-container" >
|
27 |
< canvas id = "departments" ></ canvas >
|
31 |
< div class = "push" ></ div >
|
Here, we can see that we have a basic header, middle, and footer section. We are using the .wrapper class and .push class to create a sticky footer (see here for more info). We will be creating our layout to be mobile friendly first, and to scale up from there. There are a few tricks we will pull along the way, but this structure will do a lot of the work for us.
译者信息
页面标记
咱一起先为我们的页面布局定义一些基本的HTML:
03 |
< div class = "container clearfix" >
|
04 |
< h1 >Overview < span >July 8-12, 2013</ span >< a class = "button" >Change Date Range</ a ></ h1 >
|
07 |
< div class = "container clearfix" >
|
08 |
< div class = "third widget doughnut" >
|
09 |
< h3 >Breakdown of Hours</ h3 >
|
10 |
< div class = "canvas-container" >
|
11 |
< canvas id = "hours" ></ canvas >
|
14 |
< div class = "third widget line" >
|
15 |
< div class = "chart-legend" >
|
16 |
< h3 >Shipments per Day</ h3 >
|
18 |
< div class = "canvas-container" >
|
19 |
< canvas id = "shipments" ></ canvas >
|
22 |
< div class = "third widget" >
|
23 |
< div class = "chart-legend" >
|
24 |
< h3 >Customer Service Assessment</ h3 >
|
26 |
< div class = "canvas-container" >
|
27 |
< canvas id = "departments" ></ canvas >
|
31 |
< div class = "push" ></ div >
|
这里,我们有基本的头部,内容和页脚部分。我们用.wrapper和.push类来创建粘性页脚(粘性页脚相关信息)。我们先创建支持移动设备的布局,然后在向上扩展。也许以这种方式会碰到很多陷阱,但这种结构会给我们很大帮助的。
Before We Go Too Far...
Note that canvas doesnt play extremely well with media queries. For this tutorial, we will be creating a workaround to allow the charts to be redrawn at different sizes in the JavaScript.
Inside our main.js file, we will need to have a sizing function that is triggered by a window resize. We will also need a "redraw" function to fire after the resizing function fires. Finally, when we redraw the charts, we don't want them to animate in, as if this is the first time they are being drawn.
06 |
function size(animate){
|
12 |
t = setTimeout( function (){
|
13 |
$( "canvas" ).each( function (i,el){
|
17 |
"width" :$(el).parent().width(),
|
18 |
"height" :$(el).parent().outerHeight()
|
27 |
$( ".widget" ).height( "" );
|
28 |
$( ".widget" ).each( function (i,el){ m = Math.max(m,$(el).height()); });
|
29 |
$( ".widget" ).height(m);
|
33 |
$(window).on( 'resize' , size);
|
34 |
function redraw(animation){
|
37 |
options.animation = false ;
|
39 |
options.animation = true ;
|
If this seems a little daunting, don't worry! Ask a question in the comments, and we and the Tuts+ community will help you understand fully!
译者信息
热个身先
Canvas在媒体库方面做的不是很好。下面的指南将会创建一个工作区,这个工作区将允许charts用JavaScript在不同窗口大小下重绘。
在我们的main.js文件里,我们需要有一个设置大小的函数,这个函数是在窗口大小变化时触发的,同时在大小改变后我们需要调用“重绘”函数,最终将重绘charts,但我们不让它有动态效果,让它保持第一次绘制时的样子。
06 |
function size(animate){
|
13 |
t = setTimeout( function (){
|
14 |
$( "canvas" ).each( function (i,el){
|
18 |
"width" :$(el).parent().width(),
|
19 |
"height" :$(el).parent().outerHeight()
|
29 |
$( ".widget" ).height( "" );
|
30 |
$( ".widget" ).each( function (i,el){ m = Math.max(m,$(el).height()); });
|
31 |
$( ".widget" ).height(m);
|
35 |
$(window).on( 'resize' , size);
|
36 |
function redraw(animation){
|
39 |
options.animation = false ;
|
41 |
options.animation = true ;
|
这看起来很难吧!去Tuts+社区交流交流会帮助你加深理解的。
Some CSS to Get Us Started
We want to set up some basic CSS structures to get us started. HTML5 Boilerplate of course includes normalize and some other defaults that you can change, but for the sake of the tutorial, we will write our CSS after the line "Author's custom styles".
05 |
font-family : 'Source Sans Pro' , sans-serif ;
|
14 |
text-transform : uppercase ;
|
15 |
display : inline- block ;
|
21 |
box-shadow: 0 0 2px rgba( 0 , 0 , 0 , 0.1 );
|
22 |
background : rgb ( 190 , 190 , 190 );
|
23 |
background : -moz-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% , rgba( 170 , 170 , 170 , 1 ) 100% );
|
24 |
background : -webkit-gradient(linear, left top , left bottom , color-stop( 0% ,rgba( 190 , 190 , 190 , 1 )), color-stop( 100% ,rgba( 170 , 170 , 170 , 1 )));
|
25 |
background : -webkit-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
26 |
background : -o-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
27 |
background : -ms-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
28 |
background : linear-gradient(to bottom , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
29 |
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr= '#bebebe' , endColorstr= '#aaaaaa' ,GradientType= 0 );
|
65 |
-webkit-box-sizing: border-box;
|
66 |
-moz-box-sizing: border-box;
|
67 |
box-sizing: border-box;
|
Here, we define the necessary CSS for the sticky footer, as well as a button class, a self-centering container class, a class for containing our canvas elements inside of our widgets, and our widgets themselves. We will also need to add the Google font we are defining for the body by including this in our head tag.
1 |
< link href = 'http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700' rel = 'stylesheet' type = 'text/css' >
|
译者信息
CSS准备
我们也讲讲一些CSS结构的知识吧。HTML5模板文件包含了一些普通的和一些用户可以改变的例子,但是为了我们的指南,我们将在“作者自定义风格”后写写我们自己的CSS。
05 |
font-family : 'Source Sans Pro' , sans-serif ;
|
14 |
text-transform : uppercase ;
|
15 |
display : inline- block ;
|
21 |
box-shadow: 0 0 2px rgba( 0 , 0 , 0 , 0.1 );
|
22 |
background : rgb ( 190 , 190 , 190 );
|
23 |
background : -moz-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% , rgba( 170 , 170 , 170 , 1 ) 100% );
|
24 |
background : -webkit-gradient(linear, left top , left bottom , color-stop( 0% ,rgba( 190 , 190 , 190 , 1 )), color-stop( 100% ,rgba( 170 , 170 , 170 , 1 )));
|
25 |
background : -webkit-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
26 |
background : -o-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
27 |
background : -ms-linear-gradient( top , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
28 |
background : linear-gradient(to bottom , rgba( 190 , 190 , 190 , 1 ) 0% ,rgba( 170 , 170 , 170 , 1 ) 100% );
|
29 |
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr= '#bebebe' , endColorstr= '#aaaaaa' ,GradientType= 0 );
|
65 |
-webkit-box-sizing: border-box;
|
66 |
-moz-box-sizing: border-box;
|
67 |
box-sizing: border-box;
|
这里,我们定义了有关粘性页脚所必需的CSS,包括一个按钮的类,一个自居中的类,一个包含canvas元素组件的类,以及我们组件自己用的类。我们在boby里的head标签里定义来添加Google字体。
1 |
< link href = 'http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,400,700' rel = 'stylesheet' type = 'text/css' >
|
The Doughnut Graph
Doughnut graphs are a lot like pie graphs, except they have part of the middle cut out. By default, ChartJS defines that 50% of the area of the graph should be left out; we will stay with this default. The code to create the doughnut graph is shown below.
20 |
var canvas = document.getElementById( "hours" );
|
21 |
var ctx = canvas.getContext( "2d" );
|
22 |
new Chart(ctx).Doughnut(data);
|
Here, you can see that we have defined our doughnut graph's data and colors. This is all that is needed to make the doughnut graph work. However, what are each of the sections representing? Unfortunately, ChartJS does not yet have an easy way to define labels for the doughnut graph; however, we can make our own legend to describe each of the different sections. Modify the doughnut widget's html to include the following.
01 |
< div class = "third widget doughnut" >
|
02 |
< h3 >Breakdown of Hours</ h3 >
|
03 |
< p >< a href = "" class = "button" >Filter By Employee</ a ></ p >
|
04 |
< div class = "canvas-container" >
|
05 |
< canvas id = "hours" ></ canvas >
|
06 |
< span class = "status" ></ span >
|
08 |
< div class = "chart-legend" >
|
10 |
< li class = "ship" >Shipping & Receiving</ li >
|
11 |
< li class = "rework" >Rework</ li >
|
12 |
< li class = "admin" >Administrative</ li >
|
13 |
< li class = "prod" >Production</ li >
|
译者信息
圆环圈图
圆环圈图很像馅饼圈图,除过中间被剪掉了。默认情况下,ChartJS定义将忽略50%的区域;我们保持这个默认值。下面是创建圆圈环图的代码。
20 |
var canvas = document.getElementById( "hours" );
|
21 |
var ctx = canvas.getContext( "2d" );
|
22 |
new Chart(ctx).Doughnut(data);
|
这里你可以看到我们定义了圆环圈图的数据和颜色。这是创建圆圈环图所必需的。然而,到底哪些部分需要重复呢?不幸的是,ChartJS没有简单定义标签的方式,我们只能靠我们自己用图示的方式来描述每一个部分。修改圆环圈组件的html如下:
01 |
< div class = "third widget doughnut" >
|
02 |
< h3 >Breakdown of Hours</ h3 >
|
03 |
< p >< a href = "" class = "button" >Filter By Employee</ a ></ p >
|
04 |
< div class = "canvas-container" >
|
05 |
< canvas id = "hours" ></ canvas >
|
06 |
< span class = "status" ></ span >
|
08 |
< div class = "chart-legend" >
|
10 |
< li class = "ship" >Shipping & Receiving</ li >
|
11 |
< li class = "rework" >Rework</ li >
|
12 |
< li class = "admin" >Administrative</ li >
|
13 |
< li class = "prod" >Production</ li >
|
We use these li's by their classes very simply in the CSS, by leveraging the `:before` pseudo-class.
16 |
.chart-legend li:before { |
25 |
.ship:before { background-color : #637b85 ; }
|
26 |
.rework:before { background-color : #2c9c69 ; }
|
27 |
.admin:before { background-color : #dbba34 ; }
|
28 |
.prod:before { background-color : #c62f29 ; }
|
Next, we want to have a nice "thumbs-up" in the center of the doughnut. This involves some CSS trickery, including a version of
Uncle Dave's Ol' Padded Box to get the circle to be responsive. We will use the span with the class of .status to achieve this circle. Add the following rules to main.css:
01 |
.widget.doughnut .status { |
17 |
background-color : #aaa ;
|
18 |
background-image : url (data:image/png;base 64 ,iVBORw 0 KGgoAAAANSUhEUgAAAF 8 AAABkCAQAAABK+CQQAAAACXBIWXMAAFKnAABSpwHUSB+cAAADGGlDQ 1 BQaG 90 b 3 Nob 3 AgSUNDIHByb 2 ZpbGUAAHjaY 2 BgnuDo 4 uTKJMDAUFBUUuQe 5 BgZERmlwH 6 egY 2 BmYGBgYGBITG 5 uMAxIMCHgYGBIS 8 /L 5 UBFTAyMHy 7 xsDIwMDAcFnX 0 cXJlYE 0 wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ 3 p 5 SUEJAwNjDAMDg 0 hSdkEJAwNjAQMDg 0 h 2 SJAzAwNjCwMDE 09 JakUJAwMDg 3 N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ 15 yflFBflFiSWoKAwMD 1 A 4 GBgYGXpf 8 EgX 3 xMw 8 BSMDVQYqg 4 jIKAUICxE+CDEESC 4 tKoMHJQODAIMCgwGDA 0 MAQyJDPcMChqMMbxjFGV 0 YSxlXMN 5 jEmMKYprAdIFZmDmSeSHzGxZLlg 6 WW 6 x 6 rK 2 s 99 gs 2 aaxfWMPZ 9 /NocTRxfGFM 5 HzApcj 1 xZuTe 4 FPFI 8 U 3 mFeCfxCfNN 45 fhXyygI 7 BD 0 FXwilCq 0 A/hXhEVkb 2 i 4 aJfxCaJG 4 lfkaiQlJM 8 JpUvLS 19 QqZMVl 32 llyfvIv 8 H 4 WtioVKekpvldeqFKiaqP 5 UO 6 jepRGqqaT 5 QeuA 9 iSdVF 0 rPUG 9 V/pHDBYY 1 hrFGNuayJsym 740 u 2 C+ 02 KJ 5 QSrOutcmzjbQDtXe 2 sHY 0 cdJzVnJRcFV 3 k 3 BXdlD 3 VPXS 8 Tbxsfd 99 gvwT//ID 6 wIlBS 4 N 3 hVwMfRnOFCEXaRUVEV 0 RMzN 2 T 9 yDBLZE 3 aSw 5 IaUNak 30 zkyLDIzs+ZmX 8 xlz 7 PPryjYVPiuWLskq 3 RV 2 ZsK/cqSql 01 jLVedVPrHzbqNdU 0 n 22 VaytsP 9 op 3 VXUfbpXta+x/+ 5 Em 0 mzJ/+dGj/t 8 AyNmf 2 zvs 9 JmHt 6 vvmCpYtEFrcu+bYsc/m 9 lSGrTq 9 xWbtvveWGbZtMNm/ZarJt+w 6 rnft 3 u+ 45 uy 9 s/ 4 ODOYd+Hmk/Jn 58 xUnrU+fOJJ/ 9 dX 7 SRe 1 LR 68 kXv 13 fc 5 Nm 1 t 379 TfU 75 / 4 mHeY 7 En+ 59 lvhB 5 efB 1 /lv 5 dxc+NH 0 y/fzq 64 Lv 4 T 8 Ffp 360 /rP 8 f 9 /AA 0 ADzT 6 lvFdAAAAIGNIUk 0 AAHolAACAgwAA+f 8 AAIDpAAB 1 MAAA 6 mAAADqYAAAXb 5 JfxUYAAAUYSURBVHja 1 JxdTBxVFMd/O 7 vssgvLtxIQKrSVQluNiqVp 0 xAepKSpiaFKVEyMD 2 oQNGisifFJ 06 TRN 2 xjS 2 Js 0 geNHy 9 am 5 q 0 wRhNLNZUwI 9 aQmtDMbUtSFsKLOyye 3 xgl 8 KyHwM 7 uzv 3 vwkk 99 yZ+TF 759 xzzz 0 DQko/z 8 kl 8 ckt+U 26 pEEciZ 4 vtfAu 6 ZE 7 GpUjcr 9 K+EUyIEs 1 JC 2 irf 6 MGqmUi 5 ywlvUcpnX 1 J 0 wtvhvXsrZC 3 qNeDfwcnBFa 7 +FtclXAz 8 cRsb 2 BJhXwS 7 FHbHfwJBnmx 6 +IatlCmdnxtRj 4 JdSYHd 9 JeVSbg 01 mx 8 +jJIbV 9 INnDcUxrMWrYUkl/kbcMawOs+PXYYlhtZh 78 BRSG 9 M+S 8 DM+JupimkfNTd+U 8 yRD 1 fMPHhK 2 B 3 TPsegmfEfizMtjZsZv 5 QXscbscZ 5 hs+JrtPFInD 6 nuG 1 W/D 10 xPHqY 5 xc 5 bmTvjx/VIYlnj 4 VuxkzDZo 0 y 99 x 4 SekyYyJEqd 0 yqjE 15 fiNB 9 +kXwoHh 3 wt 2 Sn+dJUZfKF+EWSe++ThV 8 sX 4 s+JTDuk 4 VvlwOiV 8 fElci 1 kuH 3 G 3 leZ 88 ZjjKd 2 Ixo/IL 8 hTix 5 R 2 d 5 btEJ 3 SjVUuD 7 r 5 fccNc+BZayNPZ 9 wrfJh 5 OGavKOHH 9 Yp 1 hyGz 4 u 1 mru+ 9 PeM 2 Fn 0 eL 7 oyBl 3 NGxOJGakecbMJSpzlmLnw 7 z 0 bYPYkmG 5 mJX 9 JmIP 4 Wdq 6 gt 4 smJsnEjg 0 NKxpa 8 LeFAH 4 C+PExwwyzeLjNNB 68 SJijE 6 PgrRzipRUdMctsENoS/BD 8 GYplAvjxM 8 csk 9 xknBEG+J 4 /F 2 WEDIt 06 uSapEL/yFuSbXTIZpNuSZW 8 clDcxuLv 0 LWuMko+ 2 T+/OjbG 82 TSTlEKc 9 U 2 XuUp 48 Z+s 9 yWVOu 8 bDDm 7 hfzBtmkWht 4 BZtmwMTXznbSoSfYmrjfb+QT 7 iI 96 k 4 Uv 5 LPqCNdupQYfj 6 HeJr 0 yWsLBlsFOCKGuoKHceaihMf 7 aSGdGrQI 1 NHJwxFLVQCm 6 KWL 35 e 1 V 7 CPZ+Jk 7 ZOr/ 2 hH 6 mUwro/tk 5 qFHE 65 VMhmeVn 6 JCDplF/eFStyUlfnriD+JumXYbkuc 5 JuHZcCwcY 2 XV/UVnKYAOysIZ/ 06 yr 7 GAdN 53 zpWigkEsygs/StZLFowVxyz 5 eVaaipB+cnS 1 Xxc+ggS 1182 MUelfEz 6 aRCXXx 4 iHaV 8 TVaVcaHTJXx/RxVGf 8 b 3 lcX/ 2 fe 5 Lqq+Bd 5 jQuq+n 0 P 79 CrbtAwwPGQ 71 Tz 7 ntVxl 8 bKuZWE 788 tPWtJr 7 G 4 /M 7 Y 6 o 6 zu 08 oDJ+IbtUxodtZKqM 78 KqMv 6 PTKmL 388 Rdcf+ZfZyUVX 8 ETroUXXaGqYtFLCphz 9 KJycWT 79 qqZtjS 6 MHlTRNz 9 IMt 1 r 4 PqbCYze 1 ZFEZXwvfClQLX 8 L 3 dtTCH+Wayvifh 7 /dpen+ 2 qI 8 PClUDweXD 55 JXYdOBVMTPm 7 iTwv 8 r 7 zO 1 fBGG 6 dp 1 HHwGSYAGKKZKqqpYT 1 lFET 5 txHG 6 xfaIhQmYJF 6 PorzJi 3008 pfS 1 qsuCmmgmpqqOJe 7 iYracMqwAn 2 Rn 4 lM 1 SSURu 1 JHeK 03 wQ 6 S 9 feBacFFHOfWykmkpKyDW 0 NneMwxyIVu 88 X 89 jpwA 7 lmU 75 haEmagFMcuVQR 6 lrKOaGtZRSBZOHGRgW 6 iOXYmP 9 /AvP/AxvdGfNkuS 9 vituMnBTS 755 JNHAfnkkUM 22 WSThQM 7 GWSQgQ 0 IIAQQfMwwzQ 3 GGOEC 5 /iDy/hiXeb/AQDtquZeJxF 4 YgAAAABJRU 5 ErkJggg==);
|
19 |
background-repeat : no-repeat ;
|
21 |
background-position : center ;
|
Perhaps the most glaring element standing out here is the use of the data URI for the background image. This allows us to avoid an extra HTTP request, and is syntactically synonymous with using an actual http url. We are also setting this element to be positioned absolutely inside its .widget element, which we previously set to be position relative.
译者信息 我们用简单的CSS类样式和:before伪类来渲染li元素。
16 |
.chart-legend li:before { |
25 |
.ship:before { background-color : #637b85 ; }
|
26 |
.rework:before { background-color : #2c9c69 ; }
|
27 |
.admin:before { background-color : #dbba34 ; }
|
28 |
.prod:before { background-color : #c62f29 ; }
|
接下来,我想在馅饼圈图中间放一个“竖起的大拇指”。这里将会使用到一些比如使用
Uncle Dave's Ol' Padded Box
来使圆圈响应的CSS技巧,我们将会用.status类样式渲染span来实现,main.css样式如下:
01 |
.widget.doughnut .status { |
17 |
background-color : #aaa ;
|
18 |
background-image : url (data:image/png;base 64 ,iVBORw 0 KGgoAAAANSUhEUgAAAF 8 AAABkCAQAAABK+CQQAAAACXBIWXMAAFKnAABSpwHUSB+cAAADGGlDQ 1 BQaG 90 b 3 Nob 3 AgSUNDIHByb 2 ZpbGUAAHjaY 2 BgnuDo 4 uTKJMDAUFBUUuQe 5 BgZERmlwH 6 egY 2 BmYGBgYGBITG 5 uMAxIMCHgYGBIS 8 /L 5 UBFTAyMHy 7 xsDIwMDAcFnX 0 cXJlYE 0 wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ 3 p 5 SUEJAwNjDAMDg 0 hSdkEJAwNjAQMDg 0 h 2 SJAzAwNjCwMDE 09 JakUJAwMDg 3 N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ 15 yflFBflFiSWoKAwMD 1 A 4 GBgYGXpf 8 EgX 3 xMw 8 BSMDVQYqg 4 jIKAUICxE+CDEESC 4 tKoMHJQODAIMCgwGDA 0 MAQyJDPcMChqMMbxjFGV 0 YSxlXMN 5 jEmMKYprAdIFZmDmSeSHzGxZLlg 6 WW 6 x 6 rK 2 s 99 gs 2 aaxfWMPZ 9 /NocTRxfGFM 5 HzApcj 1 xZuTe 4 FPFI 8 U 3 mFeCfxCfNN 45 fhXyygI 7 BD 0 FXwilCq 0 A/hXhEVkb 2 i 4 aJfxCaJG 4 lfkaiQlJM 8 JpUvLS 19 QqZMVl 32 llyfvIv 8 H 4 WtioVKekpvldeqFKiaqP 5 UO 6 jepRGqqaT 5 QeuA 9 iSdVF 0 rPUG 9 V/pHDBYY 1 hrFGNuayJsym 740 u 2 C+ 02 KJ 5 QSrOutcmzjbQDtXe 2 sHY 0 cdJzVnJRcFV 3 k 3 BXdlD 3 VPXS 8 Tbxsfd 99 gvwT//ID 6 wIlBS 4 N 3 hVwMfRnOFCEXaRUVEV 0 RMzN 2 T 9 yDBLZE 3 aSw 5 IaUNak 30 zkyLDIzs+ZmX 8 xlz 7 PPryjYVPiuWLskq 3 RV 2 ZsK/cqSql 01 jLVedVPrHzbqNdU 0 n 22 VaytsP 9 op 3 VXUfbpXta+x/+ 5 Em 0 mzJ/+dGj/t 8 AyNmf 2 zvs 9 JmHt 6 vvmCpYtEFrcu+bYsc/m 9 lSGrTq 9 xWbtvveWGbZtMNm/ZarJt+w 6 rnft 3 u+ 45 uy 9 s/ 4 ODOYd+Hmk/Jn 58 xUnrU+fOJJ/ 9 dX 7 SRe 1 LR 68 kXv 13 fc 5 Nm 1 t 379 TfU 75 / 4 mHeY 7 En+ 59 lvhB 5 efB 1 /lv 5 dxc+NH 0 y/fzq 64 Lv 4 T 8 Ffp 360 /rP 8 f 9 /AA 0 ADzT 6 lvFdAAAAIGNIUk 0 AAHolAACAgwAA+f 8 AAIDpAAB 1 MAAA 6 mAAADqYAAAXb 5 JfxUYAAAUYSURBVHja 1 JxdTBxVFMd/O 7 vssgvLtxIQKrSVQluNiqVp 0 xAepKSpiaFKVEyMD 2 oQNGisifFJ 06 TRN 2 xjS 2 Js 0 geNHy 9 am 5 q 0 wRhNLNZUwI 9 aQmtDMbUtSFsKLOyye 3 xgl 8 KyHwM 7 uzv 3 vwkk 99 yZ+TF 759 xzzz 0 DQko/z 8 kl 8 ckt+U 26 pEEciZ 4 vtfAu 6 ZE 7 GpUjcr 9 K+EUyIEs 1 JC 2 irf 6 MGqmUi 5 ywlvUcpnX 1 J 0 wtvhvXsrZC 3 qNeDfwcnBFa 7 +FtclXAz 8 cRsb 2 BJhXwS 7 FHbHfwJBnmx 6 +IatlCmdnxtRj 4 JdSYHd 9 JeVSbg 01 mx 8 +jJIbV 9 INnDcUxrMWrYUkl/kbcMawOs+PXYYlhtZh 78 BRSG 9 M+S 8 DM+JupimkfNTd+U 8 yRD 1 fMPHhK 2 B 3 TPsegmfEfizMtjZsZv 5 QXscbscZ 5 hs+JrtPFInD 6 nuG 1 W/D 10 xPHqY 5 xc 5 bmTvjx/VIYlnj 4 VuxkzDZo 0 y 99 x 4 SekyYyJEqd 0 yqjE 15 fiNB 9 +kXwoHh 3 wt 2 Sn+dJUZfKF+EWSe++ThV 8 sX 4 s+JTDuk 4 VvlwOiV 8 fElci 1 kuH 3 G 3 leZ 88 ZjjKd 2 Ixo/IL 8 hTix 5 R 2 d 5 btEJ 3 SjVUuD 7 r 5 fccNc+BZayNPZ 9 wrfJh 5 OGavKOHH 9 Yp 1 hyGz 4 u 1 mru+ 9 PeM 2 Fn 0 eL 7 oyBl 3 NGxOJGakecbMJSpzlmLnw 7 z 0 bYPYkmG 5 mJX 9 JmIP 4 Wdq 6 gt 4 smJsnEjg 0 NKxpa 8 LeFAH 4 C+PExwwyzeLjNNB 68 SJijE 6 PgrRzipRUdMctsENoS/BD 8 GYplAvjxM 8 csk 9 xknBEG+J 4 /F 2 WEDIt 06 uSapEL/yFuSbXTIZpNuSZW 8 clDcxuLv 0 LWuMko+ 2 T+/OjbG 82 TSTlEKc 9 U 2 XuUp 48 Z+s 9 yWVOu 8 bDDm 7 hfzBtmkWht 4 BZtmwMTXznbSoSfYmrjfb+QT 7 iI 96 k 4 Uv 5 LPqCNdupQYfj 6 HeJr 0 yWsLBlsFOCKGuoKHceaihMf 7 aSGdGrQI 1 NHJwxFLVQCm 6 KWL 35 e 1 V 7 CPZ+Jk 7 ZOr/ 2 hH 6 mUwro/tk 5 qFHE 65 VMhmeVn 6 JCDplF/eFStyUlfnriD+JumXYbkuc 5 JuHZcCwcY 2 XV/UVnKYAOysIZ/ 06 yr 7 GAdN 53 zpWigkEsygs/StZLFowVxyz 5 eVaaipB+cnS 1 Xxc+ggS 1182 MUelfEz 6 aRCXXx 4 iHaV 8 TVaVcaHTJXx/RxVGf 8 b 3 lcX/ 2 fe 5 Lqq+Bd 5 jQuq+n 0 P 79 CrbtAwwPGQ 71 Tz 7 ntVxl 8 bKuZWE 788 tPWtJr 7 G 4 /M 7 Y 6 o 6 zu 08 oDJ+IbtUxodtZKqM 78 KqMv 6 PTKmL 388 Rdcf+ZfZyUVX 8 ETroUXXaGqYtFLCphz 9 KJycWT 79 qqZtjS 6 MHlTRNz 9 IMt 1 r 4 PqbCYze 1 ZFEZXwvfClQLX 8 L 3 dtTCH+Wayvifh 7 /dpen+ 2 qI 8 PClUDweXD 55 JXYdOBVMTPm 7 iTwv 8 r 7 zO 1 fBGG 6 dp 1 HHwGSYAGKKZKqqpYT 1 lFET 5 txHG 6 xfaIhQmYJF 6 PorzJi 3008 pfS 1 qsuCmmgmpqqOJe 7 iYracMqwAn 2 Rn 4 lM 1 SSURu 1 JHeK 03 wQ 6 S 9 feBacFFHOfWykmkpKyDW 0 NneMwxyIVu 88 X 89 jpwA 7 lmU 75 haEmagFMcuVQR 6 lrKOaGtZRSBZOHGRgW 6 iOXYmP 9 /AvP/AxvdGfNkuS 9 vituMnBTS 755 JNHAfnkkUM 22 WSThQM 7 GWSQgQ 0 IIAQQfMwwzQ 3 GGOEC 5 /iDy/hiXeb/AQDtquZeJxF 4 YgAAAABJRU 5 ErkJggg==);
|
19 |
background-repeat : no-repeat ;
|
21 |
background-position : center ;
|
这段代码中最引人注目的可能就是背景图片所使用的数据URI了。URI在语法上等同于实际使用HTTP URL路径并且能够避免额外HTTP请求开销。同样我们在.widget样式中将它设置成了绝对定位,之前我们设置的是相对定位的。
Let's now go ahead and set up the widget typography. We only use h3 and p elements inside the widget; here is the accompanying css.
06 |
margin : -12px 0 12px -12px ;
|
The margin and padding rules on the h3 element allow the element to stretch to the edge of the widget element over the top of the widget's 12px of padding. We also set the top margin to 0 on the p element to fit closer to the header of the widget.
译者信息 现在我们设置widget的样式。在这里我们只用到了h3和p元素,它们的样式如下:
view sourceprint?
06 |
margin : -12px 0 12px -12px ;
|
h3元素的margin和padding的规则能够使得元素拉升到距离widget顶部12像素的位置,将p元素的margin设置为0能够让p元素和widget顶部贴合。