D3.js - 在 json 中使用嵌套数组绘制图像
D3.js - plotting images with nested array in json
我是d3新手,下面是我输入的json文件,
{
"y_axis_list":["A","B","C","D","E","F","G"],
"Points":[
{
"y": "A",
"x": 10,
"Persona":["link1"]
},
{
"y" : "B",
"x": 20,
"Persona":["link2","link1"]
},
{
"y" : "C",
"x": 30,
"Persona":["link2","link3"]
},
{
"y" : "D",
"x": 40,
"Persona":["link2","link3"]
},
{
"y" : "E",
"x" : 50,
"Persona":["link5","link6"]
},
{
"y" : "F",
"x" : 60,
"Persona":["link7","link8"]
},
{
"y" : "G",
"x" : 70,
"Persona":["link9","link10"]
}
]
}
以下是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>D3 v4 - linechart</title>
<style>
#graph {
width: 900px;
height: 500px;
}
.tick line {
stroke-dasharray: 2 2 ;
stroke: #ccc;
}
.x{
display: none;
}
.y path{
fill: none;
stroke: none;
/* set the CSS */
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="graph"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
!(function(){
"use strict"
var width,height
var chartWidth, chartHeight
var margin
var svg = d3.select("#graph").append("svg")
var axisLayer = svg.append("g").classed("axisLayer", true)
var chartLayer = svg.append("g").classed("chartLayer", true)
var xScale = d3.scaleLinear()
var yScale = d3.scalePoint()
var align = 0
var i=10;
//d3.tsv("data1.tsv", cast, main)
d3.json("http://localhost/newest.json",cast)
//データの方変換
function cast(datafull) {
console.log("got it");
var data=datafull["Points"];enter code here
data.forEach(function(data) {
console.log(data.y);
data.y = data.y;
data.x = +data.x;
});
main(data,datafull);
}
function main(data,datafull) {
console.log("in main");
setSize(data,datafull)
drawAxis()
drawChart(data,datafull)
}
function setSize(data,datafull) {
width = document.querySelector("#graph").clientWidth
height = document.querySelector("#graph").clientHeight
margin = {top:40, left:100, bottom:40, right:0 }
chartWidth = width - (margin.left+margin.right+8)
chartHeight = height - (margin.top+margin.bottom)
svg.attr("width", width).attr("height", height)
axisLayer.attr("width", width).attr("height", height)
chartLayer
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("transform", "translate("+[margin.left, margin.top]+")")
xScale.domain([0, d3.max(data, function(d) { return d.x; })]).range([0,chartWidth])
yScale.domain(datafull["y_axis_list"]).range([chartHeight, 0]).align(1)
}
function drawChart(data,datafull) {
console.log("in drawChart");
var t = d3.transition()
.duration(4000)
.ease(d3.easeLinear)
.on("start", function(d){ console.log("transiton start") })
.on("end", function(d){ console.log("transiton end") });
// var tooltip = d3.tip().attr('class', 'd3-tip').html(function(d) { return 10; });
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var lineGen = d3.line()
.x(function(d) { i=i+50;console.log(i); return xScale(d.x); })
.y(function(d) { return yScale(d.y) })
.curve(d3.curveStepAfter)
var line = chartLayer.selectAll(".line")
.data([data])
line.enter().append("path").classed("line", true)
.merge(line)
.attr("d", lineGen)
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width","2px")
.attr("stroke-dasharray", function(d){ return this.getTotalLength() })
.attr("stroke-dashoffset", function(d){ return this.getTotalLength() })
chartLayer.selectAll(".line").transition(t)
.attr("stroke-dashoffset", 0)
var img = chartLayer.selectAll('image')
.data(data)
.enter()
.append('image')
.attr("class","logo")
.attr("xlink:href", "http://localhost/whatsapp-logo.jpg" )
.attr("x", function(d,i){ return xScale(d.x+5/2) })
.attr("y", function(d,i){ return yScale(d.y) })
.attr("width", 16)
.attr("height", 16)
.style("opacity",0);
img.transition().delay(4000).duration(500).ease(d3.easeLinear).style("opacity",1);
img.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html("Persona people" + "<br/>" + d.x)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
chartLayer.selectAll("circle").classed("circle",true)
.data(data)
.enter().append("circle")
.attr("class", "circle")
.attr("fill","none")
.attr("stroke","black")
.attr("cx", function(d) { return xScale(d.x); })
.attr("cy", function(d) { return yScale(d.y); })
.attr("r", 4)
}
function drawAxis(){
var yAxis = d3.axisLeft(yScale)
.tickSizeInner(-chartWidth)
axisLayer.append("g")
.attr("transform", "translate("+[margin.left, margin.top]+")")
.attr("class", "axis y")
.call(yAxis);
var xAxis = d3.axisBottom(xScale)
axisLayer.append("g")
.attr("class", "axis x")
.attr("transform", "translate("+[margin.left, chartHeight+margin.top]+")")
.call(xAxis);
}
function update(){
}
}());
</script>
</body>
</html>
我希望角色列表中给出的图像与 json 中的 y 坐标显示在同一行,x 轴每分钟都在变化。链接是指向要加载的图像的链接。
我经历了很多问题,但我无法弄清楚这样做的方法。
我的当前输出如下。
现在每一行有一张图片,我希望角色列表(输入json)中的图片数量出现在每一行中。
用这种方式重写你的 img
变量(注意注释):
var img = chartLayer
.selectAll('g')
.data(data)
.enter()
.append('g') // append g element, here we will be append image as child
.attr("transform", function(d, i) {
var x = xScale(d.x + 5 / 2);
var y = yScale(d.y);
return 'translate(' + x + ', ' + y + ')'
})
.selectAll('image')
.data(function(d) { // here we format data as we need
return d.Persona.map(function(icon, index) {
return {
icon: icon,
tooltipText: d.Text[index] // set tooltip text
}
})
})
.enter()
.append('image') // append image element
.attr("class", "logo")
.attr("xlink:href", function(d) { // set appropriate href attribute
return d.icon;
})
.attr("x", function(d, i) { // move image by index
return 20 * i;
})
.attr("width", 16)
.attr("height", 16)
.style("opacity", 0);
...
img.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html("Persona people" + "<br/>" + d.tooltipText) // get tooltip text
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
...
我是d3新手,下面是我输入的json文件,
{
"y_axis_list":["A","B","C","D","E","F","G"],
"Points":[
{
"y": "A",
"x": 10,
"Persona":["link1"]
},
{
"y" : "B",
"x": 20,
"Persona":["link2","link1"]
},
{
"y" : "C",
"x": 30,
"Persona":["link2","link3"]
},
{
"y" : "D",
"x": 40,
"Persona":["link2","link3"]
},
{
"y" : "E",
"x" : 50,
"Persona":["link5","link6"]
},
{
"y" : "F",
"x" : 60,
"Persona":["link7","link8"]
},
{
"y" : "G",
"x" : 70,
"Persona":["link9","link10"]
}
]
}
以下是我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>D3 v4 - linechart</title>
<style>
#graph {
width: 900px;
height: 500px;
}
.tick line {
stroke-dasharray: 2 2 ;
stroke: #ccc;
}
.x{
display: none;
}
.y path{
fill: none;
stroke: none;
/* set the CSS */
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="graph"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
!(function(){
"use strict"
var width,height
var chartWidth, chartHeight
var margin
var svg = d3.select("#graph").append("svg")
var axisLayer = svg.append("g").classed("axisLayer", true)
var chartLayer = svg.append("g").classed("chartLayer", true)
var xScale = d3.scaleLinear()
var yScale = d3.scalePoint()
var align = 0
var i=10;
//d3.tsv("data1.tsv", cast, main)
d3.json("http://localhost/newest.json",cast)
//データの方変換
function cast(datafull) {
console.log("got it");
var data=datafull["Points"];enter code here
data.forEach(function(data) {
console.log(data.y);
data.y = data.y;
data.x = +data.x;
});
main(data,datafull);
}
function main(data,datafull) {
console.log("in main");
setSize(data,datafull)
drawAxis()
drawChart(data,datafull)
}
function setSize(data,datafull) {
width = document.querySelector("#graph").clientWidth
height = document.querySelector("#graph").clientHeight
margin = {top:40, left:100, bottom:40, right:0 }
chartWidth = width - (margin.left+margin.right+8)
chartHeight = height - (margin.top+margin.bottom)
svg.attr("width", width).attr("height", height)
axisLayer.attr("width", width).attr("height", height)
chartLayer
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("transform", "translate("+[margin.left, margin.top]+")")
xScale.domain([0, d3.max(data, function(d) { return d.x; })]).range([0,chartWidth])
yScale.domain(datafull["y_axis_list"]).range([chartHeight, 0]).align(1)
}
function drawChart(data,datafull) {
console.log("in drawChart");
var t = d3.transition()
.duration(4000)
.ease(d3.easeLinear)
.on("start", function(d){ console.log("transiton start") })
.on("end", function(d){ console.log("transiton end") });
// var tooltip = d3.tip().attr('class', 'd3-tip').html(function(d) { return 10; });
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var lineGen = d3.line()
.x(function(d) { i=i+50;console.log(i); return xScale(d.x); })
.y(function(d) { return yScale(d.y) })
.curve(d3.curveStepAfter)
var line = chartLayer.selectAll(".line")
.data([data])
line.enter().append("path").classed("line", true)
.merge(line)
.attr("d", lineGen)
.attr("fill", "none")
.attr("stroke", "blue")
.attr("stroke-width","2px")
.attr("stroke-dasharray", function(d){ return this.getTotalLength() })
.attr("stroke-dashoffset", function(d){ return this.getTotalLength() })
chartLayer.selectAll(".line").transition(t)
.attr("stroke-dashoffset", 0)
var img = chartLayer.selectAll('image')
.data(data)
.enter()
.append('image')
.attr("class","logo")
.attr("xlink:href", "http://localhost/whatsapp-logo.jpg" )
.attr("x", function(d,i){ return xScale(d.x+5/2) })
.attr("y", function(d,i){ return yScale(d.y) })
.attr("width", 16)
.attr("height", 16)
.style("opacity",0);
img.transition().delay(4000).duration(500).ease(d3.easeLinear).style("opacity",1);
img.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html("Persona people" + "<br/>" + d.x)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
chartLayer.selectAll("circle").classed("circle",true)
.data(data)
.enter().append("circle")
.attr("class", "circle")
.attr("fill","none")
.attr("stroke","black")
.attr("cx", function(d) { return xScale(d.x); })
.attr("cy", function(d) { return yScale(d.y); })
.attr("r", 4)
}
function drawAxis(){
var yAxis = d3.axisLeft(yScale)
.tickSizeInner(-chartWidth)
axisLayer.append("g")
.attr("transform", "translate("+[margin.left, margin.top]+")")
.attr("class", "axis y")
.call(yAxis);
var xAxis = d3.axisBottom(xScale)
axisLayer.append("g")
.attr("class", "axis x")
.attr("transform", "translate("+[margin.left, chartHeight+margin.top]+")")
.call(xAxis);
}
function update(){
}
}());
</script>
</body>
</html>
我希望角色列表中给出的图像与 json 中的 y 坐标显示在同一行,x 轴每分钟都在变化。链接是指向要加载的图像的链接。
我经历了很多问题,但我无法弄清楚这样做的方法。
我的当前输出如下。
现在每一行有一张图片,我希望角色列表(输入json)中的图片数量出现在每一行中。
用这种方式重写你的 img
变量(注意注释):
var img = chartLayer
.selectAll('g')
.data(data)
.enter()
.append('g') // append g element, here we will be append image as child
.attr("transform", function(d, i) {
var x = xScale(d.x + 5 / 2);
var y = yScale(d.y);
return 'translate(' + x + ', ' + y + ')'
})
.selectAll('image')
.data(function(d) { // here we format data as we need
return d.Persona.map(function(icon, index) {
return {
icon: icon,
tooltipText: d.Text[index] // set tooltip text
}
})
})
.enter()
.append('image') // append image element
.attr("class", "logo")
.attr("xlink:href", function(d) { // set appropriate href attribute
return d.icon;
})
.attr("x", function(d, i) { // move image by index
return 20 * i;
})
.attr("width", 16)
.attr("height", 16)
.style("opacity", 0);
...
img.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html("Persona people" + "<br/>" + d.tooltipText) // get tooltip text
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
...