Published
Edited
May 4, 2020
1 star
Insert cell
md`# zoom について`
Insert cell
d3 = require("d3@5", "d3-array@2")
Insert cell
margin = ({ top: 30, right: 0, bottom: 30, left: 50 })
Insert cell
width = 770
Insert cell
height = 500
Insert cell
md`## zoom の概要
zoomには要素が2つあって、

- zoom 対象のsvgオブジェクト
- zoom対象のチャートとか
- zoom オブジェクト
- どのようなzoomか?の定義をする
- zoom率(拡大、縮小率)の範囲設定 scaleExtent
- zoom可能箇所 translateExtent
- zoomのイベントが発生したときの処理内容登録
* ただ、scaleExtentとかtranslateExtentの挙動がいまいちわかっていない

を定義することでzoom処理を行う。
`
Insert cell
md`### 適当にLineチャート作成`
Insert cell
// 二次関数のグラフを書いてみる
Insert cell
data = d3.range(0, 1000).map(x => {
return {
x: x,
y: 3 * x * x + 2 * x + 1 // 3x^2 + 2x + 1
};
})
Insert cell
md`x,y scale を作成`
Insert cell
d3.extent(data, d => d.x)
Insert cell
x = d3
.scaleLinear()
.domain(d3.extent(data, d => d.x))
.range([margin.left, width - margin.right])
Insert cell
y = d3
.scaleLinear()
.domain(d3.extent(data, d => d.y))
.range([height - margin.bottom, margin.top])
Insert cell
md`折れ線グラフ用のline情報作成`
Insert cell
line = d3
.line()
.x(d => x(d.x))
.y(d => y(d.y))
Insert cell
md`x,yの軸作成`
Insert cell
xAxis = d3.axisBottom().scale(x)
Insert cell
yAxis = d3.axisLeft().scale(y)
Insert cell
md`グラフ描画`
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

svg
.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);

svg
.append("g")
.attr("class", "xaxis")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(xAxis);

svg
.append("g")
.attr("class", "yaxis")
.attr("transform", `translate(${margin.left}, 0)`)
.call(yAxis);

return svg.node();
}
Insert cell
md`## zoom オブジェクト作成`
Insert cell
zoom = (zoomTaget, xaxis, yaxis) =>
d3.zoom().on("zoom", () => {
zoomTaget.attr("transform", d3.event.transform);
xaxis.call(xAxis.scale(d3.event.transform.rescaleX(x)));
yaxis.call(yAxis.scale(d3.event.transform.rescaleY(y)));
})
Insert cell
// 指定した小数点n位で丸める
function roundFloat(number, n) {
var _pow = Math.pow(10, n);
return Math.round(number * _pow) / _pow;
}
Insert cell
chart2 = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

const target = svg
.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);

const xaxis = svg
.append("g")
.attr("class", "xaxis")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(xAxis);

const yaxis = svg
.append("g")
.attr("class", "yaxis")
.attr("transform", `translate(${margin.left}, 0)`)
.call(yAxis);

const zoomInfo = svg
.append("text")
.attr("y", height)
.text("zoom情報: ")

.attr("transform", `trnslate(0, heigth - 33`);

const zoom = d3
.zoom()
.translateExtent([[0, 0], [width - margin.right, height - margin.bottom]])
.on("zoom", () => {
target.attr("transform", d3.event.transform);
xaxis.call(xAxis.scale(d3.event.transform.rescaleX(x)));
yaxis.call(yAxis.scale(d3.event.transform.rescaleY(y)));
console.log(d3.event.transform);

const zoomRatio = roundFloat(d3.event.transform.k, 2);
const zoomX = roundFloat(d3.event.transform.x, 2);
const zoomY = roundFloat(d3.event.transform.x, 2);
zoomInfo.text(
`zoom情報: 拡大率${zoomRatio} 倍, (x, y):(${zoomX}, ${zoomY})`
);
});

svg.call(zoom);

return svg.node();
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more