将d3图表(svg)转换为图像并显示
Convert d3 chart (svg) to an image and display it
我正在尝试将 d3 图表转换为 png 图像。
我读过很多关于 SO 的问题,其中解释了如何去做。
Capture HTML Canvas as gif/jpg/png/pdf?
基本上我在尝试这个,link 中提到的,但无法让它工作。
<div class="chart" id="chart" style="width: 50%; margin: 0 auto;"></div>
<script src="/js/d3.js"></script>
<script src="/js/canvg.js"></script>
<script src="/js/jquery-2.2.0.js"></script>
<!-- d3 code -->
<script type="text/javascript">
...
var svg = d3.select(".chart").append("svg").attr("id", "mysvg").attr("width",
width + margin.left + margin.right).attr("height",
height + margin.top + margin.bottom);
...
</script>
<canvas id="canvas" width="200" height="200"></canvas>
<script type="text/javascript">
canvg(document.getElementById('canvas'), x);
var canvas = document.getElementById('canvas');
var img = canvas.toDataURL('image/png');
document.write('<img src="'+img+'"/>');
</script>
如您所见,有一个 x
作为第二个参数。
对于 x,我尝试了以下方法:
1) <svg>'+$('#chart').html()+'</svg>
2) $('svg').html()
3) document.getElementById('chart').firstChild
4) document.getElementById('mysvg')
5) $('#chart').html() (Answer by Mark, working on his example, but not on my example)
我检查了输出,对于情况 1) 实际上有一个 canvas 对象和一个图像对象,但是它们都是空白的。在其他情况下,会抛出一些异常,尤其是 3) 4).
的空指针
我对 JS 没有经验,所以这可能是一些非常基本的错误..
谁能帮忙?
编辑:
我的完整 d3 代码:
var margin = {
top : 20,
right : 20,
bottom : 30,
left : 50
}, width = 960 - margin.left - margin.right, height = 500 - margin.top
- margin.bottom;
d3.json("data/measure.json", function(error, data) {
console.log(data);
if (error)
throw error;
/* defining scales axis */
var x = d3.scale.linear().domain([ 0, d3.max(data[0].route, function(d) {return d.time; })])
.range([ 0, width ]);
var y = d3.scale.linear().domain([ d3.min(data[0].route, function(d) { return d.consume;}), d3.max(data[0].route, function(d) {return d.consume; })])
.range([ height, 0 ]);
var xAxis = d3.svg.axis().scale(x).orient("bottom")
.tickPadding(10)
.innerTickSize(-height)
.outerTickSize(0)
.ticks(data[0].route.length);
var yAxis = d3.svg.axis().scale(y).orient("left")
.tickPadding(10)
.innerTickSize(-width)
.outerTickSize(0);
// painting curves
var line = d3.svg.line().x(function(d,i) { console.log(d.time); return x(d.time);})
.y(function(d,i) { return y(d.consume); });
var foreignCurve = d3.svg.line().x(function(d,i) { return x(d.time); })
.y(function(d,i) { return y(d.consume); })
//main chart component
var svg = d3.select(".chart").append("svg").attr("width",
width + margin.left + margin.right).attr("height",
height + margin.top + margin.bottom).append("g").attr(
"transform",
"translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "x axis").call(xAxis).attr(
"transform", "translate(0," + height + ")").append("text")
.style("text-anchor", "end").attr("x", width).attr(
"y", -10).text("time (s)").attr("font-weight", "bold");
var axisG = svg.append("g");
axisG.attr("class", "y axis").attr("dx", ".5em").call(yAxis)
.append("text").attr("transform", "rotate(-90)").attr("y",
6).attr("dy", ".71em").style("text-anchor", "end")
.text("Bandwidth (Kbps)").attr("font-weight","bold");
svg.append("path").datum(data[0].route).attr("class", "line").attr(
"d", line);
svg.append("path").datum(data[0].foreign).attr("class","line2").attr("d", foreignCurve);
var group = svg.append("g");
group.append("line").attr("class", "mean-line").attr({
x1 : x(0),
y1 : y(data[0].threshold),
x2 : x(d3.max(data[0].route, function(d) {
return d.time;
})),
y2 : y(data[0].threshold)
});
group.append("line").attr("class", "mean-line").attr({
x1 : x(0),
y1 : y(data[0].threshold*1.05),
x2 : x(d3.max(data[0].route, function(d) {
return d.time;
})),
y2 : y(data[0].threshold*1.05)
});
group.append("text").style("text-anchor", "end").attr("y",
y(data[0].threshold*1.05) - 5).attr("x", x(d3.max(data[0].route, function(d) {
return d.time;
}))).attr("fill", "gray").text("buffered limit");
group.append("text").style("text-anchor", "end").attr("y",
y(data[0].threshold) + 10).attr("x", x(d3.max(data[0].route, function(d) {
return d.time;
}))).attr("fill", "gray").text("limit");
html输出(仅img标签):
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAsUlEQVR4nO3BAQEAAACCIP+vbkhAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8GXHmAAFMgHIEAAAAAElFTkSuQmCC">
这个过程称为光栅化,因此将矢量图形转换为光栅图形,即 svg(矢量图形)到 png(光栅图形)https://en.wikipedia.org/wiki/Rasterisation
这是更简单的方法(但它需要使用 npm,因此 npm 工作需要 Node.js):您必须安装 gulp-svg2png 并将其添加到您的 gulpfile.js
First, install gulp-svg2png as a development dependency:
npm install --save-dev gulp-svg2png
Then, add it to your gulpfile.js:
var svg2png = require('gulp-svg2png');
gulp.task('svg2png', function () {
gulp.src('./specs/assets/**/*.svg')
.pipe(svg2png())
.pipe(gulp.dest('./build'));
});
您需要图表 div
的 html 内容,包括 svg
标签。所以使用:
$('#chart').html()
这是一个例子:
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<script data-require="jquery@2.2.0" data-semver="2.2.0" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://rawgit.com/gabelerner/canvg/master/canvg.js"></script>
</head>
<body>
<div class="chart" id="chart" style="width: 50%; margin: 0 auto;"></div>
<!-- d3 code -->
<script type="text/javascript">
var svg = d3.select(".chart").append("svg")
.attr("id", "mysvg")
.attr("width", 500)
.attr("height", 500);
svg.selectAll('.bar')
.data([1,2,3,4])
.enter()
.append('rect')
.attr('y', function(d,i){
return d * 50;
})
.attr('height', function(d,i){
return 500 - (d * 50);
})
.attr('width', 50)
.attr('x', function(d,i){
return i * 100;
})
.style('fill', 'steelblue');
</script>
<canvas id="canvas" width="200" height="200"></canvas>
<script type="text/javascript">
canvg(document.getElementById('canvas'), $('#chart').html());
var canvas = document.getElementById('canvas');
var img = canvas.toDataURL('image/png');
document.write('<img src="' + img + '"/>');
</script>
</body>
</html>
我正在尝试将 d3 图表转换为 png 图像。 我读过很多关于 SO 的问题,其中解释了如何去做。
Capture HTML Canvas as gif/jpg/png/pdf?
基本上我在尝试这个,link 中提到的,但无法让它工作。
<div class="chart" id="chart" style="width: 50%; margin: 0 auto;"></div>
<script src="/js/d3.js"></script>
<script src="/js/canvg.js"></script>
<script src="/js/jquery-2.2.0.js"></script>
<!-- d3 code -->
<script type="text/javascript">
...
var svg = d3.select(".chart").append("svg").attr("id", "mysvg").attr("width",
width + margin.left + margin.right).attr("height",
height + margin.top + margin.bottom);
...
</script>
<canvas id="canvas" width="200" height="200"></canvas>
<script type="text/javascript">
canvg(document.getElementById('canvas'), x);
var canvas = document.getElementById('canvas');
var img = canvas.toDataURL('image/png');
document.write('<img src="'+img+'"/>');
</script>
如您所见,有一个 x
作为第二个参数。
对于 x,我尝试了以下方法:
1) <svg>'+$('#chart').html()+'</svg>
2) $('svg').html()
3) document.getElementById('chart').firstChild
4) document.getElementById('mysvg')
5) $('#chart').html() (Answer by Mark, working on his example, but not on my example)
我检查了输出,对于情况 1) 实际上有一个 canvas 对象和一个图像对象,但是它们都是空白的。在其他情况下,会抛出一些异常,尤其是 3) 4).
的空指针我对 JS 没有经验,所以这可能是一些非常基本的错误.. 谁能帮忙?
编辑: 我的完整 d3 代码:
var margin = {
top : 20,
right : 20,
bottom : 30,
left : 50
}, width = 960 - margin.left - margin.right, height = 500 - margin.top
- margin.bottom;
d3.json("data/measure.json", function(error, data) {
console.log(data);
if (error)
throw error;
/* defining scales axis */
var x = d3.scale.linear().domain([ 0, d3.max(data[0].route, function(d) {return d.time; })])
.range([ 0, width ]);
var y = d3.scale.linear().domain([ d3.min(data[0].route, function(d) { return d.consume;}), d3.max(data[0].route, function(d) {return d.consume; })])
.range([ height, 0 ]);
var xAxis = d3.svg.axis().scale(x).orient("bottom")
.tickPadding(10)
.innerTickSize(-height)
.outerTickSize(0)
.ticks(data[0].route.length);
var yAxis = d3.svg.axis().scale(y).orient("left")
.tickPadding(10)
.innerTickSize(-width)
.outerTickSize(0);
// painting curves
var line = d3.svg.line().x(function(d,i) { console.log(d.time); return x(d.time);})
.y(function(d,i) { return y(d.consume); });
var foreignCurve = d3.svg.line().x(function(d,i) { return x(d.time); })
.y(function(d,i) { return y(d.consume); })
//main chart component
var svg = d3.select(".chart").append("svg").attr("width",
width + margin.left + margin.right).attr("height",
height + margin.top + margin.bottom).append("g").attr(
"transform",
"translate(" + margin.left + "," + margin.top + ")");
svg.append("g").attr("class", "x axis").call(xAxis).attr(
"transform", "translate(0," + height + ")").append("text")
.style("text-anchor", "end").attr("x", width).attr(
"y", -10).text("time (s)").attr("font-weight", "bold");
var axisG = svg.append("g");
axisG.attr("class", "y axis").attr("dx", ".5em").call(yAxis)
.append("text").attr("transform", "rotate(-90)").attr("y",
6).attr("dy", ".71em").style("text-anchor", "end")
.text("Bandwidth (Kbps)").attr("font-weight","bold");
svg.append("path").datum(data[0].route).attr("class", "line").attr(
"d", line);
svg.append("path").datum(data[0].foreign).attr("class","line2").attr("d", foreignCurve);
var group = svg.append("g");
group.append("line").attr("class", "mean-line").attr({
x1 : x(0),
y1 : y(data[0].threshold),
x2 : x(d3.max(data[0].route, function(d) {
return d.time;
})),
y2 : y(data[0].threshold)
});
group.append("line").attr("class", "mean-line").attr({
x1 : x(0),
y1 : y(data[0].threshold*1.05),
x2 : x(d3.max(data[0].route, function(d) {
return d.time;
})),
y2 : y(data[0].threshold*1.05)
});
group.append("text").style("text-anchor", "end").attr("y",
y(data[0].threshold*1.05) - 5).attr("x", x(d3.max(data[0].route, function(d) {
return d.time;
}))).attr("fill", "gray").text("buffered limit");
group.append("text").style("text-anchor", "end").attr("y",
y(data[0].threshold) + 10).attr("x", x(d3.max(data[0].route, function(d) {
return d.time;
}))).attr("fill", "gray").text("limit");
html输出(仅img标签):
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAsUlEQVR4nO3BAQEAAACCIP+vbkhAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8GXHmAAFMgHIEAAAAAElFTkSuQmCC">
这个过程称为光栅化,因此将矢量图形转换为光栅图形,即 svg(矢量图形)到 png(光栅图形)https://en.wikipedia.org/wiki/Rasterisation
这是更简单的方法(但它需要使用 npm,因此 npm 工作需要 Node.js):您必须安装 gulp-svg2png 并将其添加到您的 gulpfile.js
First, install gulp-svg2png as a development dependency:
npm install --save-dev gulp-svg2png
Then, add it to your gulpfile.js:
var svg2png = require('gulp-svg2png'); gulp.task('svg2png', function () { gulp.src('./specs/assets/**/*.svg') .pipe(svg2png()) .pipe(gulp.dest('./build')); });
您需要图表 div
的 html 内容,包括 svg
标签。所以使用:
$('#chart').html()
这是一个例子:
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<script data-require="jquery@2.2.0" data-semver="2.2.0" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://rawgit.com/gabelerner/canvg/master/canvg.js"></script>
</head>
<body>
<div class="chart" id="chart" style="width: 50%; margin: 0 auto;"></div>
<!-- d3 code -->
<script type="text/javascript">
var svg = d3.select(".chart").append("svg")
.attr("id", "mysvg")
.attr("width", 500)
.attr("height", 500);
svg.selectAll('.bar')
.data([1,2,3,4])
.enter()
.append('rect')
.attr('y', function(d,i){
return d * 50;
})
.attr('height', function(d,i){
return 500 - (d * 50);
})
.attr('width', 50)
.attr('x', function(d,i){
return i * 100;
})
.style('fill', 'steelblue');
</script>
<canvas id="canvas" width="200" height="200"></canvas>
<script type="text/javascript">
canvg(document.getElementById('canvas'), $('#chart').html());
var canvas = document.getElementById('canvas');
var img = canvas.toDataURL('image/png');
document.write('<img src="' + img + '"/>');
</script>
</body>
</html>