N
N
Ninja Mate2016-08-09 23:47:44
JavaScript
Ninja Mate, 2016-08-09 23:47:44

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 question

Ask a Question

731 491 924 answers to any question