#reactjs #d3.js #filter #attributes #selection
#reactjs #d3.js #Фильтр #атрибуты #выбор
Вопрос:
В необработанном JavaScript есть очень простой эскиз
var actives = { active1: false, active2: true, active3: true, active4: false };
var svg = d3.select('body').append('svg').attr('width', 512).attr('height', 512);
var rect1 = svg.append("rect").attr("class", "boxElement active1 active2 active3").attr("x", 32).attr("y", 32).attr("width", 100).attr("height", 100).attr("fill", "#888888");
var rect2 = svg.append("rect").attr("class", "boxElement active1 active4").attr("x", 160).attr("y", 32).attr("width", 100).attr("height", 100).attr("fill", "#DDDDDD");
d3.selectAll('.boxElement').filter(function(){ var classes = d3.select(this).attr("class"); console.log(classes); var sum = false; Object.keys(actives).forEach(function(a_){ if(classes.includes(a_)){ console.log("found"); sum = actives[a_]; }}); return sum > 0 ? true : false }).attr("fill", "#00FF00");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
В этом случае console.log(d3.select(this)) возвращает классы rectangle, и это правильно. Мне нужно написать некоторую функцию (вместо d3.select(this).attr("class").includes("whatever")
) внутри фильтра, чтобы выбрать, какие прямоугольники будут голубыми на основе изменения класса.
Однако мне нужно сделать то же самое в ReactJS, и кажется, что ‘this’ зарезервировано, а filter console.log(d3.select(this)) возвращает сам компонент.
Синтаксис .filter(function(item_){ console.log(item_); return true; })
также не работает, он возвращает undefined
и console.log(item_.attr("class"))
возвращает ошибку.
Итак, как я могу получить доступ к каждому выбору и его атрибутам один за другим при методе фильтрации, если d3.select(this)
не работает?
Комментарии:
1. codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js Нажмите на синюю кнопку.
2. Спасибо! Речь идет о коде в
update()
? Как только я использую.filter(function() { console.log(this);});
вместо.filter(() => console.log(this));
, записанное значение снова становится правильным, в противном случае оно не определено.3. codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js Мне нужно получить доступ к attr(‘class’), однако filter(() => console.log(this.attr(‘class’); ) возвращает ошибку. «это» зарезервировано родительским компонентом, и я ищу решение для доступа к каждому выбору.
Ответ №1:
Это не элегантное решение, однако оно работает. Я использую .nodes().map(...)
import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import * as d3 from "d3";
import "./styles.css";
function App() {
return (
<div className="App">
<MockupD3 id="d3svg" />
</div>
);
}
class MockupD3 extends React.Component {
constructor(props_) {
super(props_);
this.actives = { active1: false, active2: true, active3: true, active4: false };
this.clickMe = this.clickMe.bind(this);
}
clickMe(){
let this_ = this;
d3.selectAll('.box').nodes().map(node_ => {
let sum = 0;
Object.keys(this_.actives).forEach(key_ =>{
let classes = node_.attributes.class.value;
if(classes.includes(key_)){
sum = this_.actives[key_];
}
})
if(sum > 0) { node_.attributes.fill.value = "#00FF00"; }
else { node_.attributes.fill.value = "#FF0000"; }
})
}
render() {
return ( <svg id="mockup" width={512} height={512}>
<rect class={'box active1 active2 active3'} x={64} y={64} width={64} height={64} fill={'#888888'}></rect>
<rect class={'box active1 active4'} x={160} y={64} width={64} height={64} fill={'#222222'}></rect>
<rect class={''} x={64} y={140} width={160} height={32} fill={'#0000FF'} onClick={this.clickMe}></rect>
</svg> )
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/d3-react-hooks-forked-2lihv?file=/src/index.js:0-1411
Все еще ищу подход filter ().