How to re-render only elements that have state changes #301
-
I am building a Replay component and it seems whenever the replay progress changes (min-width:${replayState.canvasStrokeIndex / st.canvas.strokesLen * 100}%;) Is there a way to only rerender the progress bar and leave everything else alone during playback? const replayState = vanX.reactive({
currentLayerIndex: 0,
layerStrokeIndex: 0,
startLayerIndex: 0,
startStrokeIndex: 0,
canvasStrokeIndex: 0,
endLayerIndex: null,
endStrokeIndex: null,
strokesPerFrameForce: null,
inProgress: false,
paused: false,
frameDuration: null,
speedMultiplier: 1,
instant: false,
exporting: false,
})
const Replay = () => {
const hover = van.state(false)
return div({ class: 'col ', style: 'pointer-events:all;width:calc(min(100rem, 80%));gap:1rem;' },
div({ class: 'cA cJ ', style: '' },
button({ onpointerdown: pauseResume, class: 'buttonSize', style: () => `color:white;fill:white;pointer-events:all;width:12rem;background-size:5rem;background-repeat:no-repeat;background-position:center;
background-image:url('./assets/toolIcons/${!replayState.inProgress || replayState.paused ? 'play' : 'pause'}.svg')` }, ''),
button({
onclick: skipReplay,
class: () => 'buttonSize',
style: 'background-size:5rem;background-repeat:no-repeat;width:10rem;background-position:center;background-image:url(./assets/toolIcons/skip.svg)'
}),
Selecter({ style: 'min-height:var(--buttonHeight);min-width:90rem;', label: 'Speed', options: [0.25, 0.5, 1, 2, 3, 5, 10], setting: vanX.stateFields(replayState).speedMultiplier }),
button({ onclick: () => { exportReplay({ extension: 'gif' }) } }, 'Save Gif'),
button({ onclick: () => { exportReplay({ extension: 'mp4' }) } }, 'Save Mp4'),
),
div({
onclick: async (e) => {
if (isClick && !mobile) {
const progress = e.offsetX / e.target.clientWidth
skipTo(progress)
}
},
ontouchend: (e) => {
if (isClick && mobile) {
const targetRect = e.target.getBoundingClientRect()
e.offsetX = e.changedTouches[0].pageX - targetRect.left
e.offsetY = e.changedTouches[0].clientY - targetRect.top
const progress = (e.changedTouches[0].pageX - targetRect.left) / e.target.clientWidth
skipTo(progress)
}
},
onpointerenter: (e) => { hover.val = true },
onpointerleave: (e) => { hover.val = false },
class: 'cJ',
style: 'cursor:pointer;position:relative;width:100%;height:8rem;border-radius:.5rem;'
},
div({ style: 'left:0;top:0rem;position:absolute;pointer-events:none;width:100%;height:4rem;background:#9191c970;border-radius:.5rem;' }),
div({
style: () => `left:0;top:0rem;position:absolute;pointer-events:none;
min-width:${replayState.canvasStrokeIndex / st.canvas.strokesLen * 100}%;
background:${hover.val ? '#ffffff3b' : '#ffffff20'};
height:4rem;
border-radius:.5rem;`
}),
div({ class: 'f1', style: 'pointer-events:none;position:absolute; left:50%;transform:translateX(-50%);top:1rem;' }, `Stroke ${replayState.canvasStrokeIndex} / ${st.canvas.strokesLen}`)),
// div({ style: () => 'pointer-events:none;top:15rem;position:absolute;height:3rem;;font-size:2rem' }, prettifyJSON(replayState))
)
}``` |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Can you try this code div({ class: 'f1', style: 'pointer-events:none;position:absolute; left:50%;transform:translateX(-50%);top:1rem;' }, () => `Stroke ${replayState.canvasStrokeIndex} / ${st.canvas.strokesLen}`)) And what parameter from replayState is changed during playback (this will allow me to test locally)? |
Beta Was this translation helpful? Give feedback.
-
replayState.canvasStrokeIndex is the one that's changed. Your change fixes it. So () => isolates updates to that element and without () => is always global rerender? |
Beta Was this translation helpful? Give feedback.
Can you try this code
And what parameter from replayState is changed during playback (this will allow me to test locally)?