Answer the question
In order to leave comments, you need to log in
How to catch already loaded svg in canvas?
The task is to make a picture from d3 svg and put it in pdf.
Everything works well, except for one moment. The png image from the d3.js chart is obtained at the moment when the animation has not yet ended (tried to set all effects to 0, it did not help)
import React, { Component } from 'react';
import { render, findDOMNode } from 'react-dom';
import { Table, Input } from 'react-bootstrap';
import d3 from 'd3';
export default class ConvertPDFSubReport extends Component {
constructor(...props) {
super(...props);
this.state = {
comments: [],
width: this.props.width,
data: this.props.data,
chartName: this.props.chartName,
tableBody: '',
date_start: this.props.date_start,
date_finish: this.props.date_finish,
docSub:'',
imgData:''
};
}
componentDidMount() {
var dataArray=this.state.data;
var that = this;
var max = d3.max(dataArray, function(d) { return d.number;} );
var margin = {top: 20, right: 5, bottom: 30, left: 53},
width = this.state.width*0.98 - margin.left - margin.right,
height = ( (width*0.75) - margin.top - margin.bottom );
var yScale = d3.scale.linear()
.domain([0, max])
.range([0, height]);
var xScale = d3.scale.ordinal()
.domain(d3.range(0, dataArray.length))
.rangeBands([0, width]);
var colors = d3.scale.linear()
.domain([0, max])
.range(["#269", "#fa1"]);
var animateDuration =0,
animateDelay = 0;
//SVG element
var myMChartSub = d3.select(this.refs.modalchart).append("svg")
.attr("id", 'myMChartSub').attr("class", 'myChartSub')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("background", 'rgba(200, 200, 200, 0.04)')
.append('g')
.attr('transform', 'translate('+margin.left+','+margin.top+')')
.selectAll("rect")
.data(dataArray)
.enter().append("rect")
.style("fill", function (d) { return colors(d.number) })
.attr("width", xScale.rangeBand()-2 )
.attr("height", function (d) { return yScale(d.number) })
.attr("x", function (d, i) { return xScale(i) })
.attr("y", height)
.attr("id", function(d,i){ return ('rectM'+ i); });// each rect has unique id
//Animation
myMChartSub.transition()
.attr('height', function(d){ return yScale(d.number) })
.attr('y', function(d){ return height - yScale(d.number) })
.duration(animateDuration)
.delay(function (d, i) { return i*animateDelay })
.ease('InBack');
var vScale = d3.scale.linear()
.domain([0, max])
.range([height, 0]);
var hScale = d3.scale.ordinal()
.domain(d3.range(1, dataArray.length+1))
.rangeBands([0, width]);
var vAxis = d3.svg.axis()
.scale(vScale)
.orient('left')
.ticks(5)
.tickFormat(d3.format("d"))
.tickSubdivide(0)
.tickPadding(5);
var vGuide = d3.select('#myMChartSub')
.append('g');
vAxis(vGuide);
vGuide.attr('transform', 'translate('+ margin.left + ','+margin.top+')' );
vGuide.selectAll('path')
.style('fill', 'none')
.style('stroke', '#ffffff');
vGuide.selectAll('line')
.style('fill', '#ffffff');
var hAxis = d3.svg.axis()
.scale(hScale)
.orient('bottom');
var hGuide = d3.select('#myMChartSub')
.append('g');
hAxis(hGuide);
hGuide.attr('transform', 'translate('+ margin.left + ','+(height + margin.top)+')' );
hGuide.selectAll('path')
.style('fill', 'none')
.style('stroke', '#ffffff');
hGuide.selectAll('line')
.style('fill', '#ffffff');
var svg = document.querySelector(".myChartSub"),
serializer = new XMLSerializer(),
svgStr = serializer.serializeToString(svg);
var img = new Image();
var canvas = document.createElement("canvas");
canvas.setAttribute("id", "canvas");
document.body.appendChild(canvas);
img.onload = function() {
canvas.style.display="none";
canvas.width = img.width ;
canvas.height = img.height ;
canvas.getContext("2d").drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = 'data:image/svg+xml;base64,' + window.btoa(svgStr);
//вот тут цепляю картинку из канваса, все работает но не успевает дорисовать даже без анимации
setTimeout(function(){
var imgData = document.querySelector("#canvas");
imgData = imgData.toDataURL("image/png");
that.setState({imgData:imgData});
//Del canvas
var elem = document.getElementById("canvas");
elem.parentNode.removeChild(elem);
}, 2000);
}
subComments(){
var that=this,
table="",
item = that.props.data;
item.map( function(item, index){
var num = 1 + index;
if(that.state.comments[index] != null){
table=table+ "" + num + " " + item.name + " " + item.number + "\n"+that.state.comments[index] + "\n\n"
}
else table=table+ "" + num + " " + item.name + " " + item.number + "\n\n";
});
//структура pdf ничего важного, все работает
var docSub = {
stack: [
{
image: that.state.imgData,
width: 400,
height: 300,
margin: [47, 3, 0, 11]
},
{
stack: [
{ text: [
table
]
}
],
fontSize: 10
}
],
styles: {
header: {
fontSize: 15,
bold: true,
alignment: 'right',
margin: [10,10,10,10]
},
footer: {
fontSize: 10,
bold: true,
alignment: 'right',
margin: [10,10,10,10]
},
link: {
fontSize: 6,
bold: false,
alignment: 'left',
margin: [20,10,10,5]
},
subheader: {
fontSize: 9,
bold: false
}
}
};
that.setState({docSub: docSub}, that.props.setSudReportString(that.state.docSub));
}
render() {
var tabl = this.props.data;
var that = this;
return (
<div id='mychart'>
<h2>{this.state.chartName}</h2>
<div ref='modalchart'></div>
<Table responsive striped bordered condensed hover>
<thead>
<tr >
<th>#</th>
<th>Name</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{
tabl.map( function(item,index)
{
return(
<tr>
<th>{1+index}</th>
<th>{item.name}</th>
<th>{item.number}</th>
<tr >
<th colSpan="3">
<Input key={index} type="textarea"
onChange={ (event)=> {
var comment = that.state.comments;
comment[index] = event.target.value;
that.setState({ comments: comment }, ()=>that.subComments());
}
}
/>
</th>
</tr>
</tr>
)
}
)
}
</tbody>
</Table>
</div>
);
}
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question