<template>
<div style="width: 100%;height:100%;position: relative">
<!-- <div
style="width:69%; font-family:arial; height: 50px;color: black; font-size: 30px; line-height: 20px; padding-left:40px;padding-top:30px;margin: 10px">
曲线拟合结果
<button
style="font-size: 13px; background: #0C0C0C; color: white; border: white; top:0px; vertical-align: middle;"
id="export"> 导出
</button>
</div>-->
<div id='chart' style="width: 100%;height:100%" ref="d3Chart"></div>
<div id='tooltip'
style="position: absolute; padding: 20px; width: 60px; background: whitesmoke; border-radius: 10px; display: none;">
<div id="color-picker-container" style="padding: 10px;left:auto;"></div>
<span> 线宽 : </span> <input id='strokewidth' value="4" style="width:80px"/>
<br>
<button style="margin-top: 10px; margin-right:10px; float: right;" id='cancel'> 取消</button>
<button style="margin-top: 10px; float: right;" id='confirm'> 确认</button>
</div>
<div id='tooltip2'
style="position: absolute; padding: 10px; width 60px; background: #060F34; border-radius: 10px; display: none;"></div>
</div>
</template>
<script>
import * as d3 from 'd3';
import { scatterDataList } from '../../assets/data/scatterData';
export default {
name: 'd3Line',
data: function () {
return {
waterDetail: {},
pollutionIndex: {}
};
},
components: {},
methods: {
calculatingData() {
const curveData = [
{
'x': '0.0001',
'label': '0',
'y': '21.4924',
'type': '1'
}, {
'x': '0.0005',
'label': '0.4285',
'y': '17.9343',
'type': '1'
}, {
'x': '0.001',
'label': '0.6288',
'y': '16.396',
'type': '1'
}, {
'x': '0.005',
'label': '1.1432',
'y': '12.8046',
'type': '1'
}, {
'x': '0.01',
'label': '1.3927',
'y': '11.2468',
'type': '1'
}, {
'x': '0.02',
'label': '1.6653',
'y': '9.6797',
'type': '1'
}, {
'x': '0.05',
'label': '2.0742',
'y': '7.5885',
'type': '1'
}, {
'x': '0.1',
'label': '2.4375',
'y': '5.9846',
'type': '1'
}, {
'x': '0.2',
'label': '2.8774',
'y': '4.3502',
'type': '1'
}, {
'x': '0.3',
'label': '3.1946',
'y': '3.371',
'type': '1'
}, {
'x': '0.4',
'label': '3.4657',
'y': '2.6595',
'type': '1'
}, {
'x': '0.5',
'label': '3.719',
'y': '2.0928',
'type': '1'
}, {
'x': '0.6',
'label': '3.9724',
'y': '1.6151',
'type': '1'
}, {
'x': '0.7',
'label': '4.2434',
'y': '1.1949',
'type': '1'
}, {
'x': '0.8',
'label': '4.5606',
'y': '0.8106',
'type': '1'
}, {
'x': '0.9',
'label': '5.0006',
'y': '0.4402',
'type': '1'
}, {
'x': '0.95',
'label': '5.3639',
'y': '0.2473',
'type': '1'
}, {
'x': '0.98',
'label': '5.7728',
'y': '0.1183',
'type': '1'
}, {
'x': '0.99',
'label': '6.0454',
'y': '0.0684',
'type': '1'
}, {
'x': '0.995',
'label': '6.2948',
'y': '0.0397',
'type': '1'
}, {
'x': '0.999',
'label': '6.8093',
'y': '0.0113',
'type': '1'
}, {
'x': '0.9995',
'label': '7.0095',
'y': '0.0066',
'type': '1'
}, {
'x': '0.9999',
'label': '7.438',
'y': '0.0019',
'type': '1'
}, {
'x': '0.0001',
'label': '0',
'y': '30.6095',
'type': '2'
}, {
'x': '0.0005',
'label': '0.4285',
'y': '24.3181',
'type': '2'
}, {
'x': '0.001',
'label': '0.6288',
'y': '21.6516',
'type': '2'
}, {
'x': '0.005',
'label': '1.1432',
'y': '15.6033',
'type': '2'
}, {
'x': '0.01',
'label': '1.3927',
'y': '13.084',
'type': '2'
}, {
'x': '0.02',
'label': '1.6653',
'y': '10.6389',
'type': '2'
}, {
'x': '0.05',
'label': '2.0742',
'y': '7.5676',
'type': '2'
}, {
'x': '0.1',
'label': '2.4375',
'y': '5.4266',
'type': '2'
}, {
'x': '0.2',
'label': '2.8774',
'y': '3.5394',
'type': '2'
}, {
'x': '0.3',
'label': '3.1946',
'y': '2.6183',
'type': '2'
}, {
'x': '0.4',
'label': '3.4657',
'y': '2.0845',
'type': '2'
}, {
'x': '0.5',
'label': '3.719',
'y': '1.7602',
'type': '2'
}, {
'x': '0.6',
'label': '3.9724',
'y': '1.5656',
'type': '2'
}, {
'x': '0.7',
'label': '4.2434',
'y': '1.4566',
'type': '2'
}, {
'x': '0.8',
'label': '4.5606',
'y': '1.404',
'type': '2'
}, {
'x': '0.9',
'label': '5.0006',
'y': '1.3858',
'type': '2'
}, {
'x': '0.95',
'label': '5.3639',
'y': '1.3836',
'type': '2'
}, {
'x': '0.98',
'label': '5.7728',
'y': '1.3834',
'type': '2'
}, {
'x': '0.99',
'label': '6.0454',
'y': '1.3834',
'type': '2'
}, {
'x': '0.995',
'label': '6.2948',
'y': '1.3834',
'type': '2'
}, {
'x': '0.999',
'label': '6.8093',
'y': '1.3834',
'type': '2'
}, {
'x': '0.9995',
'label': '7.0095',
'y': '1.3834',
'type': '2'
}, {
'x': '0.9999',
'label': '7.438',
'y': '1.3834',
'type': '2'
}, {
'x': '0.0001',
'label': '0',
'y': '34.743',
'type': '3'
}, {
'x': '0.0005',
'label': '0.4285',
'y': '26.9528',
'type': '3'
}, {
'x': '0.001',
'label': '0.6288',
'y': '23.6766',
'type': '3'
}, {
'x': '0.005',
'label': '1.1432',
'y': '16.3366',
'type': '3'
}, {
'x': '0.01',
'label': '1.3927',
'y': '13.338',
'type': '3'
}, {
'x': '0.02',
'label': '1.6653',
'y': '10.4831',
'type': '3'
}, {
'x': '0.05',
'label': '2.0742',
'y': '7.0255',
'type': '3'
}, {
'x': '0.1',
'label': '2.4375',
'y': '4.7714',
'type': '3'
}, {
'x': '0.2',
'label': '2.8774',
'y': '3.0097',
'type': '3'
}, {
'x': '0.3',
'label': '3.1946',
'y': '2.3066',
'type': '3'
}, {
'x': '0.4',
'label': '3.4657',
'y': '1.9898',
'type': '3'
}, {
'x': '0.5',
'label': '3.719',
'y': '1.8502',
'type': '3'
}, {
'x': '0.6',
'label': '3.9724',
'y': '1.795',
'type': '3'
}, {
'x': '0.7',
'label': '4.2434',
'y': '1.7772',
'type': '3'
}, {
'x': '0.8',
'label': '4.5606',
'y': '1.7731',
'type': '3'
}, {
'x': '0.9',
'label': '5.0006',
'y': '1.7726',
'type': '3'
}, {
'x': '0.95',
'label': '5.3639',
'y': '1.7726',
'type': '3'
}, {
'x': '0.98',
'label': '5.7728',
'y': '1.7726',
'type': '3'
}, {
'x': '0.99',
'label': '6.0454',
'y': '1.7726',
'type': '3'
}, {
'x': '0.995',
'label': '6.2948',
'y': '1.7726',
'type': '3'
}, {
'x': '0.999',
'label': '6.8093',
'y': '1.7726',
'type': '3'
}, {
'x': '0.9995',
'label': '7.0095',
'y': '1.7726',
'type': '3'
}, {
'x': '0.9999',
'label': '7.438',
'y': '1.7726',
'type': '3'
}]
const scatterData = scatterDataList
const cacheList=[]
/*scatterData.map((item, index)=>{
if(index%5===0){
cacheList.push(item)
}
})*/
const curveGroup={}
curveData.forEach(function (d) {
d.x = +d.x;
d.label = +d.label;
d.y = +d.y;
d.type = +d.type;
if (curveGroup[d.type] != undefined) {
curveGroup[d.type].push(d);
} else {
curveGroup[d.type] = [];
curveGroup[d.type].push(d);
}
})
// console.log(JSON.stringify(cacheList))
this.drawLine(curveGroup,scatterData)
},
drawLine(curveData, scatterData) {
let focused_line = {}
// console.log('curveData', curveData)
// console.log('scatterData', scatterData)
/*let colorPicker = new iro.ColorPicker("#color-picker-container", {
// Set the size of the color picker
width: 120,
// Set the initial color to pure red
color: "#f00",
borderColor:'#000’',
borderWidth: 2,
sliderHeight: 15,
//wheelLightness:false
});
console.log(colorPicker)*/
// const box = document.getElementById('chart');
const box = this.$refs['d3Chart']
// console.log(d3.select('#chart'))
// console.log('box', box)
// console.log(box.clientWidth)
// console.log(box.clientHeight)
let accent = d3.scaleOrdinal(d3.schemeSet2);
let height = -100 + box.clientHeight;
let width = -100 + box.clientWidth;
let curveGroup = [];
let curveGroupData = [];
let curveGenerator = d3.line()
.curve(d3.curveBasis)
.x(d => xScale(d.label))
.y(d => yScale(d.y))
for (let type in curveData) {
curveGroupData.push(curveData[type]);
curveGroup=curveGroup.concat(curveData[type])
}
console.log('curveGroupData',curveGroupData)
console.log('curveGroup',curveGroup)
scatterData.forEach(function (d) {
d.x = +d.x;
d.y = +d.y;
})
const xScale = d3.scaleLinear()
.range([0, width])
.domain([0, d3.max(curveGroup, d => d.label)])
const yScale = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(curveGroup, d => d.y)])
.nice()
// console.log(d3.select('#chart'))
// console.log(this.$refs.d3Chart.childNodes)
d3.selectAll('svg').remove()
let cc = d3.select(this.$refs.d3Chart)
.append('svg')
.attr('width', width + 100)
.attr('height', height + 100)
.attr('id', 'container')
cc.append('rect')
.attr('width', width + 100)
.attr('height', height + 100)
.attr('fill', 'rgba(255,255,255,0.1)')
let control_layer = cc.append('g')
.attr('transform', 'translate(50,50)')
let svg = cc.append('g')
.attr('transform', 'translate(50,50)')
let limit = svg.append('g')
svg.append('clipPath') // define a clip path
.attr('id', 'rect-clip') // give the clipPath an ID
.append('rect') // shape it as an ellipse
.attr('x', 0) // position the x-centre
.attr('y', 0) // position the y-centre
.attr('width', width) // set the x radius
.attr('height', height);
limit.attr('clip-path', 'url(#rect-clip)')
let locked = limit.append('g')
let yLocked = svg.append('g')
let curves = locked.selectAll('curves')
.data(curveGroupData)
.enter()
.append('path')
.attr('stroke', d => accent(d[0].type))
.datum(d => d)
.attr('d', curveGenerator)
.attr('fill', 'none')
.attr('stroke-width', 3)
.attr('id', d => d[0].type)
.on('mouseover', function (d) {
// console.log(d3.mouse(this))
d3.select('#tooltip2')
.style('display', 'block')
.html(function (q) {
var content = '<span style=\'margin-left: 2.5px;\'><b>' + 'Line: ' + d[0].type + '</b></span><br>';
return content;
})
.style('left', (d3.mouse(this)[0] + 0) + 'px')
.style('top', (d3.mouse(this)[1] + 0) + 'px')
})
.on('mouseleave', function (d) {
d3.select('#tooltip2')
.style('display', 'none')
})
.on('click', function (d) {
let str = d3.select(this)
.attr('stroke')
let c = d3.color(str)
// colorPicker.color.rgb = c
let width = d3.select(this)
.attr('stroke-width')
document.getElementById('strokewidth').value = width
d3.select('#tooltip')
.style('display', 'block')
.style('left', (d3.mouse(this)[0] + 100) + 'px')
.style('top', (d3.mouse(this)[1] - 100) + 'px')
focused_line = d3.select(this)
})
// 绘制点
let scatterPlot = locked.selectAll('.point')
.data(scatterData)
.enter()
.append('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 3)
.attr('or', 3)
.attr('fill', '#12C2C9')
.attr('stroke', 'none')
.on('mouseover', function (d) {
d3.select('#tooltip2')
.style('display', 'block')
.html(function (q) {
var content = '';
content +=
` <table style="margin-top: 2.5px;">
<tr><td>X value: </td><td style="text-align: left">` + d.x + `</td></tr>
<tr><td>Y value: </td><td style="text-align: left">` + d.y + `</td></tr>
</table>
`;
return content;
})
.style('left', (d3.mouse(this)[0] + 80) + 'px')
.style('top', (d3.mouse(this)[1] + 100) + 'px')
})
.on('mouseleave', function (d) {
d3.select('#tooltip2')
.style('display', 'none')
})
// 垂直分割线
let grids = locked.selectAll('.grids')
.data(curveGroupData[0])
.enter()
.append('line')
.attr('class', 'gridline')
.attr('x1', d => xScale(d.label))
.attr('x2', d => xScale(d.label))
.attr('y1', 0)
.attr('y2', height + 100)
.attr('stroke', '#C7B299')
.attr('ow', 1)
.attr('stroke-width', 1)
.attr('stroke-opacity', '0.3')
.attr('fill', 'none')
let yGridsData = [];
for (let i = 0; i < height; i += 20) {
yGridsData.push(i);
}
// 水平分割线
locked.selectAll('.yGrids')
.data(yGridsData)
.enter()
.append('line')
.style('pointer-events', 'none')
.attr('class', 'gridline')
.attr('x1', 0)
.attr('x2', width)
.attr('y1', d => d)
.attr('y2', d => d)
.attr('ow', 1)
.attr('stroke-width', 1)
.attr('stroke', '#C7B299')
.attr('stroke-dasharray', '2 2 2 2')
.attr('fill', 'none')
.attr('stroke-opacity', 0.2)
let xTickText = yLocked.selectAll('.axisText')
.data(curveGroupData[0])
.enter()
.append('g')
.attr('transform', d => 'translate(' + xScale(d.label) + ',' + (height + 20) + ')')
xTickText
.append('text')
.attr('x', 0)
.attr('y', 0)
.attr('transform', 'rotate(30)')
.attr('text-anchor', 'left')
.attr('font-size', 11)
.attr('font-family', 'Arial')
.attr('fill', '#00EEFF')
.text(d => d.x)
// 上边框
svg.append('line')
.attr('x1', 0)
.attr('x2', width)
.attr('y1', 0)
.attr('y2', 0)
.attr('stroke', '#12C2C9')
.attr('fill', 'none')
.attr('stroke-width', 1)
// 下边框
svg.append('line')
.attr('x1', 0)
.attr('x2', width)
.attr('y1', height)
.attr('y2', height)
.attr('stroke', '#12C2C9')
.attr('fill', 'none')
.attr('stroke-width', 1)
// 左边框
svg.append('line')
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', height)
.attr('stroke', '#12C2C9')
.attr('fill', 'none')
.attr('stroke-width', 1)
// 右边框
svg.append('line')
.attr('x1', width)
.attr('x2', width)
.attr('y1', 0)
.attr('y2', height)
.attr('stroke', '#12C2C9')
.attr('fill', 'none')
.attr('stroke-width', 1)
const yAxis = d3.axisRight(yScale)
const gY = svg.append('g')
.attr('transform', 'translate(' + width + ',0)')
.call(yAxis)
gY.attr('color', '#12C2C9')
.attr('stroke', '#B0B0B0')
.selectAll('text')
.attr('font-size', 11)
.attr('font-family', 'Arial')
let legendLines = svg.selectAll('.legend_lines')
.data(curveGroupData)
.enter()
.append('line')
.style('pointer-events', 'none')
.attr('id', d => d[0].type)
.attr('x1', function (d, i) {
return i * 120 + 0
})
.attr('x2', function (d, i) {
return i * 120 + 50
})
.attr('y1', -30)
.attr('y2', -30)
.attr('stroke', function (d) {
return accent(d[0].type)
})
.attr('stroke-width', 2)
svg.selectAll('.legend_lines')
.data(curveGroupData)
.enter()
.append('text')
.attr('x', function (d, i) {
return i * 120 + 60
})
.attr('y', -25)
.attr('font-family', 'arial')
.attr('fill', 'white')
.text(d => d[0].type)
d3.select('#confirm')
.on('click', function (d) {
// var hex = colorPicker.color.hexString;
let strokeWidth = document.getElementById('strokewidth').value
focused_line.attr('stroke', hex)
focused_line.attr('stroke-width', strokeWidth)
d3.select('#tooltip')
.style('display', 'none')
let id = focused_line.attr('id')
legendLines.attr('stroke', function (q) {
if (d3.select(this)
.attr('id') == id) {
return hex
} else {
return d3.select(this)
.attr('stroke')
}
})
})
d3.select('#cancel')
.on('click', function (d) {
d3.select('#tooltip')
.style('display', 'none')
})
d3.select('#export')
.on('click', function (d) {
let canvas = d3.select('#container')
var svgString = getSVGString(canvas.node());
svgString2Image(svgString, width + 100, height + 100, 'png', save); // passes Blob and filesize String to the callback
function save(dataBlob, filesize) {
saveAs(dataBlob, 'chart.png'); // FileSaver.js function
}
})
control_layer.append('rect')
.attr('fill', 'none')
.attr('width', width)
.attr('height', height)
.style('pointer-events', 'all')
.call(d3.zoom()
.scaleExtent([1, 8])
.translateExtent([[0, 0], [width + 90, height + 100]])
.on('zoom', zoomed))
.on('click', function (d) {
d3.select('#tooltip')
.style('display', 'none')
})
function zoomed() {
gY.call(yAxis.scale(d3.event.transform.rescaleY(yScale)));
// this.axises.yContainer.call(this.axises.y.scale(d3.event.transform.rescaleY(this.axises.yScale)))
console.log(yScale)
console.log(d3.event.transform)
console.log(d3.event.transform.rescaleY(yScale))
console.log(yAxis.scale(d3.event.transform.rescaleY(yScale)))
locked.attr('transform', d3.event.transform);
xTickText
.attr('transform', function (d) {
let x = d3.event.transform.rescaleX(xScale)(d.label)
let y = height + 20
return 'translate(' + x + ',' + y + ')'
})
locked.selectAll('circle')
.attr('r', function (d) {
let or = d3.select(this)
.attr('or')
let nr = or / d3.event.transform.k
return nr
})
locked.selectAll('.gridline')
.attr('stroke-width', function (d) {
let ow = d3.select(this)
.attr('ow')
let nw = ow / d3.event.transform.k
return nw
})
}
// FilePond.parse(document.body);
},
wheel(e) {
// preventDefault(e);
},
disable_scroll() {
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', this.wheel, false);
}
window.onmousewheel = document.onmousewheel = this.wheel;
// document.onkeydown = keydown;
}
},
watch: {},
props: ['year', 'month'],
mounted: function () {
this.disable_scroll()
// this.calculatingData()
}
};
</script>
<style scoped>
* {
font: 12px arial
}
button {
font: 10px arial
}
#tooltip {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#tooltip2 {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
</style>
用D3画散点,折线图
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 此种图是先计算再画图,好处是对理解ggplot运行原理很有帮助,坏处是加显著性比较困难,且再添加散点图还要重新加载...
- 更新完整版,修复了几个小问题,提供了测试数据下载最新版见此 EOF(经验正交分解)是气候研究中常用的研究变量时空变...
- 先看画折线图 观察两组数据的关联关系 我们举例,有两组数据,一组数据是dgp 一组是对应的年份。那么我们可以画出年...
- # 折线图/散点图 plot # import matplotlib.pylab as pyl # import ...