Ini kali pertama saya menggunakan d3.js, jadi harap bersabar. Saya melaksanakannya sebagai JavaScript tulen dalam fail vue.js. Saya cuba membuat plot taburan dengan fungsi zum. Setakat ini saya mempunyai hampir semuanya berfungsi dengan baik, tetapi apabila saya membuat skala, saya dapati bahawa paksi-x tidak berskala dengan betul, tetapi paksi-y berfungsi dengan baik. Sebagai contoh, apabila melihat graf asal, satu titik mungkin sekitar 625 pada paksi-x, tetapi apabila dizum dalam titik yang sama akan menjadi lebih kecil daripada 600. Ini tidak berlaku pada paksi-y - skala mata dengan betul. Saya mengandaikan terdapat sesuatu yang salah dengan penskalaan paksi-x dalam fungsi penskalaan, tetapi saya tidak dapat memikirkannya. Sila lihat dan beritahu saya jika anda dapat melihat di mana silap saya.
EDIT: Saya harus menyebut ini menggunakan d3.js versi 7.4.4
<template> <div id="reg_plot"></div> </template> <script> import * as d3 from 'd3'; export default { name: 'regCamGraph', components: { d3 }, methods: { createSvg() { // dimensions var margin = {top: 20, right: 20, bottom: 30, left: 40}, svg_dx = 1400, svg_dy =1000, chart_dx = svg_dx - margin.right - margin.left, chart_dy = svg_dy - margin.top - margin.bottom; // data var y = d3.randomNormal(400, 100); var x_jitter = d3.randomUniform(-100, 1400); var d = d3.range(1000) .map(function() { return [x_jitter(), y()]; }); // fill var colorScale = d3.scaleLinear() .domain(d3.extent(d, function(d) { return d[1]; })) .range([0, 1]); // y position var yScale = d3.scaleLinear() .domain(d3.extent(d, function(d) { return d[1]; })) .range([chart_dy, margin.top]); // x position var xScale = d3.scaleLinear() .domain(d3.extent(d, function(d) { return d[0]; })) .range([margin.right, chart_dx]); console.log("chart_dy: " + chart_dy); console.log("margin.top: " + margin.top); console.log("chart_dx: " + chart_dx); console.log("margin.right: " + margin.right); // y-axis var yAxis = d3.axisLeft(yScale); // x-axis var xAxis = d3.axisBottom(xScale); // zoom var svg = d3.select("#reg_plot") .append("svg") .attr("width", svg_dx) .attr("height", svg_dy); svg.call(d3.zoom().on("zoom", zoom)); // ref [1] // plot data var circles = svg.append("g") .attr("id", "circles") .attr("transform", "translate(200, 0)") .selectAll("circle") .data(d) .enter() .append("circle") .attr("r", 4) .attr("cx", function(d) { return xScale(d[0]); }) .attr("cy", function(d) { return yScale(d[1]); }) .style("fill", function(d) { var norm_color = colorScale(d[1]); return d3.interpolateInferno(norm_color) }); // add y-axis var y_axis = svg.append("g") .attr("id", "y_axis") .attr("transform", "translate(75,0)") .call(yAxis).style("font-size", "20px") // add x-axis var x_axis = svg.append("g") .attr("id", "x_axis") .attr("transform", `translate(${margin.left}, ${svg_dy - margin.bottom})`) .call(xAxis).style("font-size", "20px") function zoom(e) { // re-scale y axis during zoom y_axis.transition() .duration(50) .call(yAxis.scale(e.transform.rescaleY(yScale))); // re-scale x axis during zoom x_axis.transition() .duration(50) .call(xAxis.scale(e.transform.rescaleX(xScale))); // re-draw circles using new y-axis scale var new_xScale = e.transform.rescaleX(xScale); var new_yScale = e.transform.rescaleY(yScale); console.log(d); x_axis.call(xAxis.scale(new_xScale)); y_axis.call(yAxis.scale(new_yScale)); circles.data(d) .attr('cx', function(d) {return new_xScale(d[0])}) .attr('cy', function(d) {return new_yScale(d[1])}); } } }, mounted() { this.createSvg(); } } </script>
Menariknya, masalah itu seolah-olah selesai sendiri selepas saya menetapkan kawasan keratan untuk mengelakkan titik di luar paksi daripada dipaparkan. Beginilah cara saya mencipta laluan keratan:
// clip path var clip = svg.append("defs").append("svg:clipPath") .attr("id", "clip") .append("svg:rect") .attr("id", "clip-rect") .attr("x", "0") .attr("y", "0") .attr('width', chart_dx) .attr('height', chart_dy);
Saya kemudian menambah atribut itu pada svg apabila memplot data seperti ini:
svg.append("g").attr("clip-path", "url(#clip)")
Laluan keratan dikemas kini dengan bahagian data lukisan:
// clip path var clip = svg.append("defs").append("svg:clipPath") .attr("id", "clip") .append("svg:rect") .attr("id", "clip-rect") .attr("x", "0") .attr("y", "0") .attr('width', chart_dx) .attr('height', chart_dy); // plot data var circles = svg.append("g") .attr("id", "circles") .attr("transform", "translate(75, 0)") .attr("clip-path", "url(#clip)") //added here .selectAll("circle") .data(d) .enter() .append("circle") .attr("r", 4) .attr("cx", function(d) { return xScale(d[0]); }) .attr("cy", function(d) { return yScale(d[1]); }) .style("fill", function(d) { var norm_color = colorScale(d[1]); return d3.interpolateInferno(norm_color) });
Saya akhirnya menyelesaikan masalah itu. Saya telah mengemas kini siaran asal untuk menunjukkan perkara yang berkesan untuk saya.
Pada asasnya, selepas menambah kawasan keratan, semuanya mula berfungsi dengan baik.