缩放和拖动功能不适用于画布(D3js)

时间:2018-03-21 10:45:37

标签: javascript d3.js canvas zoom drag

我有时候一直在努力解决这个问题,真的需要帮助。我想创建一个热图,内容和轴都是可扩展的,并且可以相应地进行缩放。注意我已经将svg内容转换为画布。我想我已经在那里了一半,不幸的是我无法使画布变焦并相应地拖动,同时轴本身也没问题。

以下是我的来源,真的需要你的帮助。谢谢,抱歉我的语法不好。



$(document).ready(function() {
    let w = $('#bodyBackground')[0];
    let clientWidthz = w.clientWidth;
    let clientHeightz = w.clientHeight;
    var radars = [];
    var newSample = [];
    var timeStampLegends = [];

    for (var i = 0; i < 1440; i++) {
        var legend_xTime = new Date(Date.now() - (i * 60 * 1000));
        timeStampLegends.push(legend_xTime);
    }
    for (var unit_i = 0; unit_i <= 101;) {
        if (unit_i == 0) {
            radars.push(1);
            unit_i = unit_i + 5;
        } else {
            radars.push(unit_i);
            unit_i = unit_i + 4;
        }
    }
    //by using below method we can observe the delay is not due to the data during insertion
    for (var unit = 1; unit <= 5; unit++) {
        timeStampLegends.forEach(function(dbData) {
            var i = Math.random() * 1400;
            newSample.push({ radars: unit, timestamp: dbData, level: i });
        });
    }
    var margin = { top: 20, right: 20, bottom: 30, left: 60 };
    var width = 1200 - margin.left - margin.right;
    var height = 500 - margin.top - margin.bottom;

    var x = d3.scaleTime()
        .domain([new Date(timeStampLegends[0]), new Date(timeStampLegends[timeStampLegends.length - 1])])
        .range([0, width]);

    var min = d3.min(newSample, function(d) {
        return d.radars;
    });

    var max = d3.max(newSample, function(d) {
        return d.radars;
    });

    var y = d3.scaleLinear()
        .domain([min, max])
        .range([0, height]);

    var xAxis = d3.axisTop(x).tickSize(height); //the size of the inner grid line (vertical - x-axis)

    var yAxis = d3.axisLeft(y).ticks(5).tickSize(-width); //the size of the inner grid line (horizontal - y - axis)

    var zoom = d3.zoom()
        .translateExtent([
            [0, 0],
            [width + 2000, height]
        ])
        .scaleExtent([1, 10])
        .on("zoom", zoomed);

    var svg = d3.select(".TrafficCongestions").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 + ")");

    var canvas = d3.select('.TrafficCongestions').append("canvas")
        .attr("id", "canvas")
        //absolute: a feature that allows any sort of element
        //to be positioned disregards to other elements
        //i.e. it will calculate its own position again from (0,0)
        .style("position", "absolute")
        .style("top", "20px")
        .style("left", "60px")
        .attr("width", width + margin.left + margin.right) //optimization
        .attr("height", height + margin.top + margin.bottom);//optimization

    var context = canvas.node().getContext("2d");
    context.clearRect(0, 0, width, height);
    var detachedContainer = document.createElement("custom");
    var dataContainer = d3.select(detachedContainer);   

    var colorScale = d3.scaleLinear().domain([0, 600, 1200]).range(["#009933", "#FFCC00", "#990000"]);

    //x-axis (solely based on data of times)
    var timeLabels = svg.append("g")
        .attr("class", "x-axis")
        .attr("transform", "translate(0," + (height) + ")")
        .style("font-size", "20px")
        .call(xAxis);

    //y-axis (solely based on data of radars)
    var radarLabels = svg.append("g")
                        .attr("class", "y-axis")
                        .call(yAxis);

    //console.log(JSON.stringify(newSample));
    var heatMap = dataContainer.selectAll(".custom.rect")
                .data(newSample)
                .enter().append("custom")
                .attr("x", function(d){
                    return x(d.timestamp);
                })
                .attr("y", function(d){
                    return y(d.radars);
                })
                .classed("rect", true)
                .attr("class", "rect bordered")
                .attr("width", function(d){
                    var offSetX = x(d3.timeMinute.offset(d.timestamp, 1))- x(d.timestamp);
                    return offSetX;
                })
                //.attr("width", "1120px")
                .attr("height", function(d){
                    var offSetY = y(d.radars - 1) - y(d.radars);
                    return offSetY;
                })
                //.attr("strokeStyle", "rgba(255,255,255,0.2)")
                .attr("fillStyle", function(d, i){
                    return colorScale(d.level);
                });

    canvas.call(zoom);

    drawCanvas();

    function drawCanvas(){
        var elements = dataContainer.selectAll("custom.rect");

        elements.each(function(d){
            var node = d3.select(this);

            context.beginPath();
            context.fillStyle = node.attr("fillStyle");
            context.rect(node.attr("x"), node.attr("y"), node.attr("width"), node.attr("height"));
            context.fill();
            context.closePath();
        });
    }

    function zoomed() {
        var currentTransform = d3.event.transform;
        // update: rescale x axis
        timeLabels.call(xAxis.scale(d3.event.transform.rescaleX(x)));
        update();
    }

    function update() {
        // update: cache rescaleX value
        var rescaleX = d3.event.transform.rescaleX(x);
        heatMap.selectAll(".custom.rect")
            // update: apply rescaleX value
            .attr("x", function(d) {
                return rescaleX(d.timestamp);
            })
            .attr("y", function(d) {
                return y(d.radars);
            })
            // update: apply rescaleX value
            .attr("width", function(d) {
                return rescaleX(d3.timeMinute.offset(d.timestamp, 1)) - rescaleX(d.timestamp);
                //return rescaleX(x);
            })
            .attr("height", function(d) {
                return y(d.radars - 1) - y(d.radars);
            })
            //.attr("strokeStyle", "rgba(255,255,255,0.2)")
            .attr("fillStyle", function(d, i){
                    return colorScale(d.level);
            });

        drawCanvas();
    }
});
&#13;
body {
  position: relative;
  width: 960px;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
&#13;
<script
  src="https://code.jquery.com/jquery-1.10.0.min.js"
  integrity="sha256-2+LznWeWgL7AJ1ciaIG5rFP7GKemzzl+K75tRyTByOE="
  crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<html>
<head>
    <title></title>
</head>

<body id="bodyBackground">
	<div class="TrafficCongestions"></div>

</body>
</html>
&#13;
&#13;
&#13;

0 个答案:

没有答案