d3.js 入門指南 - 儀表盤

D3的全稱是Data-Driven Documents(數據驅動的文檔),是一個用來作數據可視化的JavaScript函數庫,而JavaScript文件的後綴一般爲.js,因此D3被稱爲D3.js。html

d3.js能夠定製出各類圖形,今天來用d3.js製做一個簡易的儀表盤,廢話很少說先上demo,接下來分步講解。數組

1.繪製svg,並分組(group)

const height = 600; //畫布高度
const width = 1200; //畫布寬度
const outerRadius = 200; //儀表盤外半徑
const innerRadius = 190; //儀表盤內半徑
const svg = d3.select('body').append('svg').attr('width', width).attr('height', height).style('background', '#000000'); // 在body中添加寬高並繪製背景色
const group = svg.append('g').attr('class', 'group').attr('transform', `translate(${width * 0.5}, ${height * 0.5})`); //添加分組並將分組中心移至畫布中心
const arc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius) //編寫弧生成器並傳入內外半徑
const keduListB = [0,1,2,3,4,5,6,7,8,9,10,11,12]; //(大)刻度的數組
const keduListS = [0,1,2,3,4,5,6,7,8,9,10,11]; //(小)刻度的數組
const radiusScaleB = d3.scaleLinear().domain([0, 12]).range([Math.PI * (- 2 / 3), Math.PI * 2 / 3]) //(大)刻度線性比例尺
const radiusScaleS = d3.scaleLinear().domain([0, 11]).range([Math.PI * (- 11 / 18), Math.PI * ( 11 / 18 )]) //(小)刻度線性比例尺
let baseData = 0; //設置基礎速度

2.將內容分組

group.append('g').attr('class', 'pan') //繪製儀表盤的圓弧分組
group.append('g').attr('class', 'kedu_b') //繪製大刻度分組
group.append('g').attr('class', 'kedu_s') //繪製小刻度分組
group.append('g').attr('class', 'zhizhen') //繪製指針分組
group.append('g').attr('class', 'shuzi') //繪製刻度數字分組
group.append('g').attr('class', 'show') //繪製速度框和數字分組
group.append('g').attr('class', 'button') //繪製按鈕框和數字分組

3.繪製儀表盤的圓弧

group.select('.pan').append('path').attr('d', arc({startAngle: radiusScaleB(0),endAngle: radiusScaleB(12)})).attr('fill', '#6AE3F8').attr('stroke', '#6AE3F8');

4.繪製大刻度

group.select('.kedu_b') .selectAll('line') .data(keduListB) .enter() .append('line') .attr('x1', d => 200 * Math.sin(radiusScaleB(d))) .attr('y1', d => 200 * Math.cos(radiusScaleB(d)) * -1) .attr('x2', d => 176 * Math.sin(radiusScaleB(d))) .attr('y2', d => 176 * Math.cos(radiusScaleB(d)) * -1) .attr('stroke', '#6AE3F8') .attr('stroke-width', 5)

5.繪製小刻度

group.select('.kedu_s') .selectAll('line') .data(keduListS) .enter() .append('line') .attr('x1', d => 200 * Math.sin(radiusScaleS(d))) .attr('y1', d => 200 * Math.cos(radiusScaleS(d)) * -1) .attr('x2', d => 180 * Math.sin(radiusScaleS(d))) .attr('y2', d => 180 * Math.cos(radiusScaleS(d)) * -1) .attr('stroke', '#6AE3F8') .attr('stroke-width', 2)

6.繪製刻度數字

group.select('.shuzi') .selectAll('text') .data(keduListB) .enter() .append('text') .attr('x', d => 160 * Math.sin(radiusScaleB(d))) .attr('y', d => 160 * Math.cos(radiusScaleB(d)) * -1) .attr('text-anchor', 'middle') .attr('dy', '0.35em') .attr('fill', '#6AE3F8') .style('text-shadow', '0px 0px 2px #6AE3F8') .text(d => d * 20)

7.繪製指針

group.select('.zhizhen') .append('polygon') .attr('points', '-2,-20,2,-20,4,0,1,140,-1,140,-4,0') .attr('fill', '#6AE3F8') .attr('transform', 'rotate(60)')

8.繪製速度框和數字

group.select('.show') .attr('transform', 'translate(0, 100)') .append('rect') .attr('x', -60) .attr('y', 0) .attr('width', 120) .attr('height', 40) .attr('fill', 'none') .attr('stroke', '#6AE3F8') .attr('stroke-width', 3) group.select('.show') .append('text') .attr('text-anchor', 'middle') .attr('x', 0) .attr('y', 20) .attr('dy', '0.35em') .attr('fill', '#6AE3F8') .attr('stroke', '#6AE3F8') .attr('font-size', '20px') .text(`0 km/h`)

9.繪製按鈕框和數字

d3.select('.button') .append('rect') .attr('x', -50) .attr('y', 250) .attr('width', 100) .attr('height', 40) .attr('fill', 'none') .attr('stroke', '#6AE3F8') .attr('stroke-width', 2) d3.select('.button') .append('text') .attr('x', 0) .attr('y', 270) .attr('text-anchor', 'middle') .attr('dy', '.35em') .attr('fill', '#6AE3F8') .attr('font-size', '20px') .text('加速')

10.速度不斷減少,而且點擊「加速」持續加速

d3.select('.button') .attr('cursor', 'pointer') .on('click', () => { if (baseData < 220) { baseData += 20 change() } else if (baseData < 240) { baseData = 240; change() } }) setInterval(() => { if (baseData > 10) { baseData -= 10; change(); } else if (baseData > 0) { baseData = 0; change() } }, 2000)

11.控制加速的方法(指針旋轉,速度數字增長)

const change = () => { group.select('.zhizhen') .transition() .duration(2000) .ease(d3.easeLinear) .attrTween('transform', function () { this._before = typeof this.getAttribute('transform') == 'string' ? this.getAttribute('transform').match(/\d+/g)[0] : 0; this._after = baseData; console.log('this._before',this._before) console.log('this._after',this._after) let interpolate = d3.interpolate(this._before, this._after); return function(t) { texts(interpolate(t)) return `rotate(${interpolate(t)})` }; }) } const texts = text => { group.select('.show').select('text') .attr('text-anchor', 'middle') .attr('x', 0) .attr('y', 20) .attr('dy', '0.35em') .attr('fill', '#6AE3F8') .attr('stroke', '#6AE3F8') .attr('font-size', '20px') .text(`${Math.floor(text)} km/h`)
}

這樣點擊加速就會調用change()方法,而change()方法在過渡是就會調用texts()方法。
這樣子就行了,一個基本的儀表盤就繪製好了app

 

原創博客:轉載請註明d3.js 入門指南 - 儀表盤dom

相關文章
相關標籤/搜索