victorzadorozhnyy
@victorzadorozhnyy

Как поймать в canvas уже загруженную svg?

Задача сделать из d3 svg картинку и засунуть в pdf.
Все хорошо работает, кроме одного момента. Картинка png с графика d3.js получается в момент, когда анимация еще не закончилась (пробовал ставить на 0 все эфекты, не помогло)
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>
        );
    }
}
  • Вопрос задан
  • 313 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы