ठीक है, इसलिए मैंने इस पर एक और ध्यान दिया है - जैसा कि मेरे पिछले उत्तर में बताया गया है , सबसे बड़ा मुद्दा जिसे आपको दूर करने की आवश्यकता है वह यह है कि डी 3-ज़ूम केवल सममित स्केलिंग की अनुमति देता है। यह एक ऐसी चीज है जिस पर व्यापक रूप से चर्चा की गई है , और मुझे विश्वास है कि माइक बेसिकॉक इसे अगले रिलीज में संबोधित कर रहे हैं।
इसलिए, समस्या को दूर करने के लिए, आपको कई ज़ूम व्यवहार का उपयोग करने की आवश्यकता है। मैंने एक चार्ट बनाया है जिसमें तीन, प्रत्येक अक्ष के लिए एक और प्लॉट क्षेत्र के लिए एक है। एक्सएंडवाई जूम व्यवहार का उपयोग कुल्हाड़ियों को स्केल करने के लिए किया जाता है। जब भी X & Y जूम व्यवहार द्वारा एक ज़ूम ईवेंट उठाया जाता है, तो उनके अनुवाद मूल्यों को प्लॉट क्षेत्र में कॉपी किया जाता है। इसी तरह, जब भूखंड क्षेत्र पर अनुवाद होता है, तो x & y घटकों को संबंधित अक्ष व्यवहारों में कॉपी किया जाता है।
प्लॉट क्षेत्र पर स्केलिंग थोड़ी अधिक जटिल है क्योंकि हमें पहलू अनुपात बनाए रखने की आवश्यकता है। इसे प्राप्त करने के लिए, मैं पिछले ज़ूम ट्रांसफ़ॉर्म को स्टोर करता हूं और स्केल डेल्टा का उपयोग करके एक्सएंडवाई जूम व्यवहार पर लागू करने के लिए एक उपयुक्त पैमाने पर काम करता हूं।
सुविधा के लिए, मैंने यह सब एक चार्ट घटक में लपेटा है:
const interactiveChart = (xScale, yScale) => {
const zoom = d3.zoom();
const xZoom = d3.zoom();
const yZoom = d3.zoom();
const chart = fc.chartCartesian(xScale, yScale).decorate(sel => {
const plotAreaNode = sel.select(".plot-area").node();
const xAxisNode = sel.select(".x-axis").node();
const yAxisNode = sel.select(".y-axis").node();
const applyTransform = () => {
// apply the zoom transform from the x-scale
xScale.domain(
d3
.zoomTransform(xAxisNode)
.rescaleX(xScaleOriginal)
.domain()
);
// apply the zoom transform from the y-scale
yScale.domain(
d3
.zoomTransform(yAxisNode)
.rescaleY(yScaleOriginal)
.domain()
);
sel.node().requestRedraw();
};
zoom.on("zoom", () => {
// compute how much the user has zoomed since the last event
const factor = (plotAreaNode.__zoom.k - plotAreaNode.__zoomOld.k) / plotAreaNode.__zoomOld.k;
plotAreaNode.__zoomOld = plotAreaNode.__zoom;
// apply scale to the x & y axis, maintaining their aspect ratio
xAxisNode.__zoom.k = xAxisNode.__zoom.k * (1 + factor);
yAxisNode.__zoom.k = yAxisNode.__zoom.k * (1 + factor);
// apply transform
xAxisNode.__zoom.x = d3.zoomTransform(plotAreaNode).x;
yAxisNode.__zoom.y = d3.zoomTransform(plotAreaNode).y;
applyTransform();
});
xZoom.on("zoom", () => {
plotAreaNode.__zoom.x = d3.zoomTransform(xAxisNode).x;
applyTransform();
});
yZoom.on("zoom", () => {
plotAreaNode.__zoom.y = d3.zoomTransform(yAxisNode).y;
applyTransform();
});
sel
.enter()
.select(".plot-area")
.on("measure.range", () => {
xScaleOriginal.range([0, d3.event.detail.width]);
yScaleOriginal.range([d3.event.detail.height, 0]);
})
.call(zoom);
plotAreaNode.__zoomOld = plotAreaNode.__zoom;
// cannot use enter selection as this pulls data through
sel.selectAll(".y-axis").call(yZoom);
sel.selectAll(".x-axis").call(xZoom);
decorate(sel);
});
let xScaleOriginal = xScale.copy(),
yScaleOriginal = yScale.copy();
let decorate = () => {};
const instance = selection => chart(selection);
// property setters not show
return instance;
};
यहाँ काम कर रहे उदाहरण के साथ एक कलम है:
https://codepen.io/colineberhardt-the-bashful/pen/qBOEEGJ