[英]D3JS interpolateSpectral
我不确定我是否了解如何使用 D3 的 interpolateSpectral 来获得我的配色方案。 当我尝试以下我的颜色工作时,问题是我不知道我可能需要多少潜在的颜色,所以我想使用 interpolateSpectral 来获得我的数据集要求的尽可能多的颜色。
当我这样做时
const color = d3.scaleOrdinal(d3.schemeCategory10);
g.selectAll('.chart-arc')
.data(pie(data))
.enter()
.append('path')
.attr('class', 'chart-arc')
.attr('d', arc)
.style('fill', d => console.log(color(d.data.label)))
.on('mouseover', this.mouseover.bind(this))
.on('mousemove', this.mousemove.bind(this))
.on('mouseout', this.mouseout.bind(this))
;
这些颜色在我可以看到它们记录到我的控制台时起作用。
当我这样做时...
const color = d3.scaleSequential(d3.interpolateSpectral);
g.selectAll('.chart-arc')
.data(pie(data))
.enter()
.append('path')
.attr('class', 'chart-arc')
.attr('d', arc)
.style('fill', d => console.log(color(d.data.label)))
.on('mouseover', this.mouseover.bind(this))
.on('mousemove', this.mousemove.bind(this))
.on('mouseout', this.mouseout.bind(this))
;
控制台将所有颜色实例记录为未定义。
更新
这是 vue.js/d3js 页面的完整代码。
<template>
<div>
<div v-if="!loading" id="chart"></div>
<div v-if="loading">Loading...</div>
</div>
</template>
<script>
import * as d3 from 'd3';
import axios from "axios";
export default {
name: "piechart2",
data(){
this.loadData()
.then((theData) => (
this.data = theData,
this.createChart
))
.finally(() => (
this.loading = false,
this.loadChart()
));
return{
data: "",
element: 'body',
width: 600,
height: 400,
loading: true
}
},
methods: {
loadData: function(){
return axios.get('http://localhost:8080/mockdata/piemock.json')
.then(result => { return result; })
.catch(error => { console.error(error); throw error; });
},
loadChart: function () {
let newData = this.data.data.map(
obj => {
return {
value: obj.count,
label : obj.label
}
}
);
let newJson = {data: newData, width: this.width, height: this.height, element: this.element}
var {data, width, height, element} = newJson;
const svg = d3.select(element)
.append('svg')
.attr('class', 'chart-svg')
.attr('width', width)
.attr('height', height)
;
this.tooltip = d3.select(element)
.append('div')
.attr('class', 'tooltip')
.style('display', 'none')
;
// const color = d3.scaleOrdinal(d3.schemeCategory10)
// ;
// console.log(color(1))
console.log(data.length)
const color = d3.scaleSequential(d3.interpolateSpectral).domain([0, data.length]);//d3.scaleSequential(d3.interpolateSpectral);
// console.log(color2(1))
const r = Math.min(width, height) / 3;
const arc = d3.arc()
.innerRadius(0)
.outerRadius(r)
;
const pie = d3.pie()
.value(d => d.value)
;
const g = svg.append('g')
.attr('transform', `translate(${width / 2},${height / 2})`)
;
g.selectAll('.chart-arc')
.data(pie(data))
.enter()
.append('path')
.attr('class', 'chart-arc')
.attr('d', arc)
.style('fill', d => console.log(color(d.data.label)))
.on('mouseover', this.mouseover.bind(this))
.on('mousemove', this.mousemove.bind(this))
.on('mouseout', this.mouseout.bind(this))
;
const l = svg.append('g')
.attr('transform', `translate(0,${height - 20})`);
const xl = d3.scaleBand()
.range([0, width])
.padding(0.3)
.domain(data.map(d => d.label))
;
const legend = l.selectAll('.chart-legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'chart-legend')
.attr('transform', (d) => `translate(${xl(d)},0)`)
;
legend.append('rect')
.attr('width', 12)
.attr('height', 12)
.style('fill', color)
;
legend.append('text')
.attr('x', 20)
.attr('y', 10)
.text(d => d)
;
},
mouseover() {
this.tooltip
.style('display', 'inline-block')
.style('position', 'absolute')
;
},
mousemove() {
this.tooltip
.text([d3.event.pageX, d3.event.pageY].join(','))
.style('left', d3.event.pageX + 10 + "px")
.style('top', d3.event.pageY + 10 + "px")
;
},
mouseout() {
this.tooltip
.style('display', 'none')
;
},
render() {
// move rendering logic down here
}
}
}
</script>
<style>
.tooltip {
background-color: rgba(0,0,0,0.75);
padding: 15px;
border-radius: 2px;
font-family: sans-serif;
color: white;
pointer-events: none;
box-shadow: 0 0 5px #999999;
}
.chart-svg {
border: 1px solid #ddd;
}
.chart-legend {
font-family: 'Open Sans', sans-serif;
}
</style>
这是JSON
[{"label": "Assamese", "count": 13},
{"label": "Bengali", "count": 83},
{"label": "Bodo", "count": 1.4},
{"label": "Dogri", "count": 2.3},
{"label": "Gujarati", "count": 46},
{"label": "Hindi", "count": 300},
{"label": "Kannada", "count": 38},
{"label": "Kashmiri", "count": 5.5},
{"label": "Konkani", "count": 5},
{"label": "Maithili", "count": 20},
{"label": "Malayalam", "count": 33},
{"label": "Manipuri", "count": 1.5},
{"label": "Marathi", "count": 73},
{"label": "Nepali", "count": 2.9},
{"label": "Oriya", "count": 33},
{"label": "Punjabi", "count": 29},
{"label": "Sanskrit", "count": 0.01},
{"label": "Santhali", "count": 6.5},
{"label": "Sindhi", "count": 2.5},
{"label": "Tamil", "count": 61},
{"label": "Telugu", "count": 74},
{"label": "Urdu", "count": 52}]
顺序尺度确实采用两个数值作为输入域( 源)。
这意味着输入应该是一个数字,并输出一个颜色。
似乎在问题中,尝试使用文本标签作为输入,这导致了问题。
不建议使用顺序色标来映射不相关的值:色标表示值之间的“接近”,并将用于不一定连接/相似的标签。
如果来自d3-scale- schemeSet3
的 12 种颜色分类比例schemeSet3
不够,可以使用iWantHue 之类的工具生成比例,优化具有可区分颜色的机会。
如果决定继续使用d3.interpolateSpectral
的切片颜色的方法,那么这个 notebook可以作为参考。 它说明了如何使用d3-scale-chromatic
方案来映射离散值(将选择菜单切换到Discrete(n)
而不是Continuous
以查看正在运行的代码)。
方法是将每个标签映射到配色方案的一部分:
// assumption: an array called `labels` has been created, containing the unique label values
let n = labels.length
, colorbyValue = {}
for (let i = 0; i < n; ++i) {
colorbyValue[labels[i]] = d3.rgb(d3.interpolateSpectral(i / (n - 1))).hex();
}
// then use with colorByValue[d.data.label]
您缺少域,请尝试以下操作:
const color = d3.scaleSequential(d3.interpolateSpectral).domain([0, data.length]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.