[英]Using transitions in React Hooks and D3
我正在嘗試復制在 React with Hooks 中看到的量規。 這是我第一次使用 D3.js,盡管我設法復制了儀表本身,但行為有點奇怪(指針的轉換不起作用),我並不完全理解 useEffect 和 D3 之間的動態。 基本上我想添加兩個針,它們每個都會接收不同的值,並在它們的值發生變化時使用轉換。
//declaring angle value
const [angle1, setAngle1] = useState(0)
//useEffect hook
useEffect(() => {
const outerR = Math.min(window.innerWidth, window.innerHeight) / 2
const svg = select(svgRef.current)
svg.selectAll('*').remove()
const EXTRA_ANGLE = 15
const angleScale = scaleLinear()
.domain([0, 100])
.range([-90 - EXTRA_ANGLE, 90 + EXTRA_ANGLE])
const arcAxis = axisRadialInner(
angleScale.copy().range(angleScale.range().map(deg2rad)),
outerR - 5
)
svg
.attr('width', outerR * 2)
.attr('height', outerR * 1.5)
.attr(
'viewBox',
`${-outerR} ${-outerR * 0.8} ${outerR * 2} ${outerR * 1}`
)
.append('g')
.classed('axis', true)
.call(arcAxis)
const needle1 = svg
.append('g')
.attr('transform', `scale(${outerR * 0.85})`)
.append('path')
.classed('needle1', true)
.attr(
'd',
['M0 -1', 'L0.03 0', 'A 0.03 0.03 0 0 1 -0.03 0', 'Z'].join(' ')
)
.transition()
.attr('transform', `rotate(${angleScale(angle1)})`)
const needle2 = svg
.append('g')
.attr('transform', `scale(${outerR * 0.85})`)
.append('path')
.classed(needle2, true)
.attr(
'd',
['M0 -1', 'L0.03 0', 'A 0.03 0.03 0 0 1 -0.03 0', 'Z'].join(' ')
)
.transition()
.attr('transform', `rotate(${angleScale(angle2)})`)
// Add val label
const label = svg
.append('text')
.classed('label', true)
.attr('x', 0)
.attr('y', outerR * 0.2)
.attr('text-anchor', 'middle')
.text(angle1)
function deg2rad (deg) {
return (deg * Math.PI) / 180
}
}, [angle1, angle2])
//updating an angle
function updateAngle1(){
setInterval(() => {
setAngle1(angle1 => angle1 + 1)
}, 200);
Angle1 和 angle2 是通過 useState 鈎子更新的,但是過渡不起作用並且使針看起來有問題。 如果沒有過渡,它可以正常工作,但是針的運動看起來很粗糙。 我不確定問題是否出在我整合 d3 部分的方式上,或者是否所有重新渲染(因為我正在並行更改兩個值)影響鈎子的性能,也許我應該以不同的方式更新角度方法。 感謝您的時間!
我不是react
專家,但在我看來你想創建兩個useEffect
塊。 第一個,只觸發一次以進行初始d3
設置。 第二,更新你的角度並移動指針。
const {useState, useEffect} = React; const App = () => { //declaring angle value let [angle1, setAngle1] = useState(0); function deg2rad (deg) { return (deg * Math.PI) / 180; } const EXTRA_ANGLE = 15; const angleScale = d3.scaleLinear().domain([0, 100]).range([-90 - EXTRA_ANGLE, 90 + EXTRA_ANGLE]); useEffect(() => { const svg = d3.select('svg'); const outerR = Math.min(window.innerWidth, window.innerHeight) / 2; const arcAxis = d3.axisRadialInner( angleScale.copy().range(angleScale.range().map(deg2rad)), outerR - 5 ); svg.attr('width', outerR * 2).attr('height', outerR * 1.5).attr( 'viewBox', `${-outerR} ${-outerR * 0.8} ${outerR * 2} ${outerR * 1}` ).append('g').classed('axis', true).call(arcAxis); const needle1 = svg.append('g').attr('transform', `scale(${outerR * 0.85})`).append('path').classed('needle1', true).attr( 'd', ['M0 -1', 'L0.03 0', 'A 0.03 0.03 0 0 1 -0.03 0', 'Z'].join(' ') ); // Add val label const label = svg.append('text').classed('label', true).attr('x', 0).attr('y', outerR * 0.2).attr('text-anchor', 'middle'); // kick off updates setInterval(() => { angle1 += 1; if (angle1 > 100) angle1 = 100; setAngle1(angle1); }, 500); },[]) useEffect(() => { d3.select('.needle1').transition().attr('transform', `rotate(${angleScale(angle1)})`); d3.select('.label').text(angle1); }, [angle1]) return <svg></svg>; } // Render it ReactDOM.render( <App />, document.getElementById("react") );
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/d3-radial-axis@1.6.4/dist/d3-radial-axis.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="react"></div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.