d3のズーム動作を使用して、d3チャートでズーミングとスケーリングを正しく抑制しようとしています。私は問題を次の最小限の実行可能な例に減らしました。ユーザーがy軸上の0行の下を見ることができないようにズームできないようにします。d3でズームとパンを制限する
サンプルはズームされていない状態で、translateExtent
をsvgの完全な高さに設定すると動作しますが、ユーザーが少しズームするとすぐに途切れます。実際、ズームインするほど、負の領域をさらに見ることができます。
translateExtent
を設定するにはどうすればよいですか?
各ズームイベントで線と軸を再描画しているのは、通常、私はsvgをレンダリングしてd3を計算に使用するためです。しかし、私はもっと簡潔に例。
const data = [ 0, 15, 30, 32, 44, 57, 60, 60, 85];
// set up dimensions and margins
const full = { w: 200, h: 200 };
const pct = { w: 0.7, h: 0.7 };
const dims = { w: pct.w * full.w, h: pct.h * full.h };
const margin = { w: (full.w - dims.w)/2, h: (full.h - dims.h)/2 };
// scales
const x = d3.scaleLinear()
.rangeRound([0, dims.w])
.domain([0, data.length]);
const y = d3.scaleLinear()
.rangeRound([dims.h, 0])
.domain(d3.extent(data));
// axes
const axes = {
x: d3.axisBottom().scale(x).tickSize(-dims.w),
y: d3.axisLeft().scale(y).tickSize(-dims.h)
}
const g = d3.select('.center');
// actual "charting area"
g
.attr('transform', `translate(${margin.w}, ${margin.h})`)
.attr('width', dims.w)
.attr('height', dims.h)
// x-axis
g.append('g')
.attr('transform', `translate(0, ${dims.h})`)
.attr('class', 'axis x')
.call(axes.x)
// y-axis
g.append('g')
.attr('class', 'axis y')
.call(axes.y)
// generator for the line
const line = d3.line()
.x((_, i) => x(i))
.y(d => y(d));
// the actual data path
const path = g
.append('path')
.attr('class', 'path')
.attr('d', line(data))
.attr('stroke', 'black')
.attr('fill', 'none')
const zoomBehaviour = d3.zoom()
.scaleExtent([1, 10])
.translateExtent([[0,0], [Infinity, full.h]])
.on('zoom', zoom);
d3.select('svg.chart').call(zoomBehaviour);
function zoom() {
const t = d3.event.transform;
const scaledX = t.rescaleX(x);
const scaledY = t.rescaleY(y);
axes.x.scale(scaledX);
axes.y.scale(scaledY);
d3.select('.axis.x').call(axes.x);
d3.select('.axis.y').call(axes.y);
line
.x((_, i) => scaledX(i))
.y(d => scaledY(d));
const scaledPath = path.attr('d', line(data));
}
body {
width: 200px;
height: 200px;
}
svg.chart {
width: 200px;
height: 200px;
border: 1px solid black;
}
.axis line, .axis path {
stroke: grey;
}
<script src="https://d3js.org/d3.v4.js"></script>
<body>
<svg class="chart">
<g class="center"></g>
</svg>
</body>
悲しいことに、これは私が必要とする動作とは異なる動作をします。この例では、画像のどの部分も不可視になることはないので、ズームインは実質的に不可能です。あなたが提供したリンクで試してみると、サンプル画像をズームインすることはできません。 ズームインすると画像を「過去」にパンすることができないようにしたい、つまり画像の一部分を常に表示する必要があります。 – DeX3
私はあなたのユースケースの正確な解決策として上記を意味するものではなく、単にあなたのアパレルには存在しない余分なステップを示すようなものであり、これは 't.x'と' t.y'の条件付きの突然変異です。 Mikeの例では、コンテンツ全体を常に可視に制限しながら、内容を制限しながら(ビュー内のコンテンツの境界ボックス)、ビューポートを「囲む」ために、条件を調整することができます。ちょうど別の条件(コンテンツバウンディングボックスとビューポートボックスは、あなたのニーズを理解すれば、マイクの例とは逆の関係にあります)。 –
うん、私はそれを動作させることができました。私は正しい方向に私を指摘した最後にあなたの答えの理由を受け入れるでしょう。誰かが最終的に動作させるようなコードを見たいと思ったら、別の答えとして投稿します。 – DeX3