D3のデータに基づいて線を描き、色を付けています。同じデータセット内のさまざまな機能に基づいてこれらの線の色を更新したいのですが、色変更機能(colorP2)が機能しません-この色の変更は役に立たないように見えますが、後でボタンによってトリガーされます。
何か案は?以下は私のコードです。
[更新] Andrew Reedが指摘したように、私の質問とは関係のないコードにエラーがありました。これを修正して、以下のコードでマークしました。
index.html
<html>
<head>
<style>
.line {
stroke-width: 4px;
fill: none;
}
</style>
</head>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script type="module">
import {drawLines} from './drawLines.js';
d3.json("test.geojson").then(drawLines);
</script>
<body>
<svg id='map'></svg>
<button onclick="colorP1()">colorP1</button>
<button onclick="colorP2()">colorP2</button>
<!-- <svg id="data" class="map_frame"></svg> -->
</body>
</html>
drawLines.js
function colorInterpolate(data, property) {
let max_d = d3.max(data.features.map(d => d.properties[property]));
let range = [max_d, 1];
return d3.scaleSequential().domain(range).interpolator(d3.interpolateViridis);
}
export function drawLines(data) {
let width = 900,
height = 500,
initialScale = 1 << 23,
initialCenter = [-74.200698022608137, 40.034504451003734]
let svg = d3.select('#map')
.attr('height', height)
.attr('width', width)
let projection = d3.geoMercator()
.scale(initialScale)
.center(initialCenter)
.translate([width / 2, height / 2])
let path = d3.geoPath(projection)
let myColor = colorInterpolate(data, 'p1');
let lines = svg.append('g')
lines.selectAll('path')
.data(data.features)
.join('path') // previously wrong, error was unrelated to question, as pointed out by Andrew.
.attr('class', 'line')
.attr('d', path)
.attr("stroke", function(d) {
return myColor(d.properties.p1);
})
colorP2();
function colorP2() {
let myColor = colorInterpolate(data, 'p2');
lines.selectAll('path')
.data(data.features)
.join()
.attr("stroke", function(d) {
return myColor(d.properties.p2);
})
}
}
test.geojson
{
"type": "FeatureCollection",
"name": "lines",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 3, "p1": 1, "p2": 3}, "geometry": { "type": "LineString", "coordinates": [ [ -74.201304101157845, 40.033790926216739 ], [ -74.201226425025339, 40.033761910802717 ], [ -74.201164135201353, 40.033738641825124 ] ] } },
{ "type": "Feature", "properties": { "id": 4, "p1": 2, "p2": 2}, "geometry": { "type": "LineString", "coordinates": [ [ -74.200521185229846, 40.034804885753857 ], [ -74.200535458528648, 40.034780636493231 ], [ -74.200698022608137, 40.034504451003734 ], [ -74.200932444446437, 40.034106179618831 ], [ -74.201017665586349, 40.033961391736824 ] ] } }
]
}
解決
最終的には、色変更関数でデータを結合する必要はありません。要素は、データがバインドされた状態ですでに存在しています。結合は、データ配列内のすべてのアイテムに1つのDOM要素が存在することを保証することを目的としています。代わりに、要素を選択して、それらの属性/スタイルを変更するだけです。
lines.selectAll('path')
.attr("stroke", function(d) { return myColor(d.properties.p2); })
問題
正確なコードを完全に共有していないのではないかと強く疑っています。共有している場合は、パスが無効なSVG要素に配置されるため、何も描画しないでください<undefined></undefined>
。
通常、結合を使用して要素を再選択できます(必要がない場合でも)。結合は入力と更新の両方の選択を返すためです。しかし、selection.join()
ここでは正しく使用していません。パスを最初に追加するときは、通常.join
、selection.append()
:を使用するのではなく、渡されるパラメーターとして結合する要素のタイプを指定します。
selection.join('path')
作成する要素のタイプを指定しないと、次のように要素が作成されます<undefined></undefined>
。ソースコードは、要素が結合ステートメントにどのように入力されるかを示しています。
enter.append(onenter + "");
にonenter
渡される最初のパラメータはどこにありますか.join
。
有効なSVG要素を指定していないため、SVGはその要素またはその子(パス)をレンダリングする方法を知りません。
var svg = d3.select("svg");
var rects = svg.selectAll("rect")
.data([1,2])
.join()
.append("rect")
.attr("x", d=>d*100+50)
.attr("y", 100)
.attr("width", 30)
.attr("height", 30)
.attr("fill","crimson");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>
最終的には.join("path")
、-を使用する必要があります。比較のために、以下はそれぞれで何が起こるかを分析します。
// Don't specify any tag:
var a = d3.select("div")
.selectAll(null) // this doesn't affect the type of element entered in the join
.data([1])
.join()
.text("a");
console.log(".join() :", a.node(), "parent:", a.node().parentNode);
// join without specifying a tag, then append
var b = d3.select("div")
.selectAll(null)
.data([1])
.join()
.append("p")
.text("b");
console.log(".join().append('p') : ", b.node(), "parent:", b.node().parentNode);
// Specify the type of element to join (the correct method):
var c = d3.select("div")
.selectAll(null)
.data([1])
.join("p")
.text("c");
console.log(".join('p') :", c.node(), "parent:", c.node().parentNode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div></div>
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加