Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Canvasでピアノロールを作る Canvasでスクロールを扱う際の 座標計算と苦労 / ng...
Search
OKUNOKENTARO
January 18, 2019
Technology
0
1.1k
Canvasでピアノロールを作る Canvasでスクロールを扱う際の 座標計算と苦労 / ng-kyoto Angular Meetup #9
2019/1/18、ng-kyoto Angular Meetup #9 にて発表した資料です。
OKUNOKENTARO
January 18, 2019
Tweet
Share
More Decks by OKUNOKENTARO
See All by OKUNOKENTARO
トレタO/X アーキテクチャ移行記 Next.js App Router化への道のり / TORETA TECH UPDATE 1
okunokentaro
5
9.6k
Podcastを継続する技術 / refactoradio-240119
okunokentaro
1
160
Webアプリケーション設計の第一歩は ディレクトリの整理から / Encraft 1
okunokentaro
34
9.9k
JSONとJSON Schemaを改めて理解する / tokyo_study
okunokentaro
9
2.2k
それでもどうしてRecoilを使うのか / Harajuku.ts Meetup Recoil
okunokentaro
19
5.4k
TypeScriptは10年でこんなに進化しました / TechFeed Experts Night 11
okunokentaro
6
1.7k
Hasura.io RDBをサクサク作る方法はARやO/RMだけじゃなくなりました/hasura-io
okunokentaro
5
620
コードには型アノテーションよりも要件アノテーションを増やせ!/harajukuts2
okunokentaro
14
6.2k
10年と3ヶ月でWebサービスを作った話 / Piyogrammer Conference 2021
okunokentaro
2
1k
Other Decks in Technology
See All in Technology
誰も全体を知らない ~ ロールの垣根を超えて引き上げる開発生産性 / Boosting Development Productivity Across Roles
kakehashi
1
230
データプロダクトの定義からはじめる、データコントラクト駆動なデータ基盤
chanyou0311
2
310
適材適所の技術選定 〜GraphQL・REST API・tRPC〜 / Optimal Technology Selection
kakehashi
1
460
Terraform未経験の御様に対してどの ように導⼊を進めていったか
tkikuchi
2
430
Can We Measure Developer Productivity?
ewolff
1
150
Evangelismo técnico: ¿qué, cómo y por qué?
trishagee
0
360
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
これまでの計測・開発・デプロイ方法全部見せます! / Findy ISUCON 2024-11-14
tohutohu
3
370
個人でもIAM Identity Centerを使おう!(アクセス管理編)
ryder472
3
210
いざ、BSC討伐の旅
nikinusu
2
780
SREが投資するAIOps ~ペアーズにおけるLLM for Developerへの取り組み~
takumiogawa
1
260
AWS Lambda のトラブルシュートをしていて思うこと
kazzpapa3
2
170
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
169
14k
Fireside Chat
paigeccino
34
3k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Building Adaptive Systems
keathley
38
2.3k
How GitHub (no longer) Works
holman
310
140k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
A designer walks into a library…
pauljervisheath
204
24k
Into the Great Unknown - MozCon
thekraken
32
1.5k
Happy Clients
brianwarren
98
6.7k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.8k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
Transcript
$BOWBTͰϐΞϊϩʔϧΛ࡞Δ $BOWBTͰεΫϩʔϧΛѻ͏ࡍͷ ࠲ඪܭࢉͱۤ࿑ +BO OHLZPUP"OHVMBS.FFUVQ !PLVOPLFOUBSP
୭ w Ԟݡଠ!PLVOPLFOUBSP w ΫϨεΣΞද w ΞϓϦέʔγϣϯ ɾ ΤϯδχΞ
࠷ۙͬͨ͜ͱ w 8FC.VTJDͰԿ͕Ͱ͖Δͷ͔ '30/5&/%$0/'&3&/$& w ͷ τϥΠΤϥʔ͔Βੜ·Εͨେنઃܭϊϋ 'SPOUFOE$POGFSFODF'VLVPLB w ࣍ੈ8FCΧϯϑΝϨϯε8FC.VTJDηογϣϯ
࣍ੈ8FCΧϯϑΝϨϯε
ࠓ͢͜ͱ w $BOWBTͰϐΞϊϩʔϧΛ࣮͢Δ w 3FBDU)PPLTͱԿ͔ w $BOWBTΛѻ͏্Ͱͷۤ࿑
ϐΞϊϩʔϧͱ
ϐΞϊϩʔϧ ͍͍ͩͨͲͷԻ੍ָ࡞༻ͷιϑ τΣΞʹ࣮͞Ε͍ͯΔ ϝϩσΟ Λೖྗ͢ΔͨΊͷΤσΟ λը໘
%FNP
Ͱ͖Δ͜ͱ Ϋ Ϧ οΫͰͷԻූͷೖྗ υϥ οάͰͷԻූͷมߋ ϐΞϊϩʔϧදࣔͷ9ํɺ :ํͷ֦େॖখɺ εΫϩʔϧ ʢσϞͯ͠ͳ͍͚Ͳɺ
ԻූͷίϐϖআͨΓલʹͰ͖Δʣ
ͳʹ͛ʹߴػೳ w Ի੍ָ࡞༻ιϑ τ %"8 ઐੑ͕ߴ͍ͨΊಛԽͨ͠ػೳ͕ଟ͍ w ςΩε τΤσΟ λʹൺΔͱང͔ʹಛघͳ࣮
w (6*࣮Λੜۀͱ͢Δϑϩϯ τΤϯ υ ɾ ΤϯδχΞͱͯ͠ ͜ΕΛͪΌΜͱ࣮Ͱ͖ΔͱεΩϧΞοϓ͢ΔͷͰ
ͬͯΈͨ
3FBDU $BOWBT w OHLZPUP"OHVMBS.FFUVQͰൃදͯ͠Δ͚Ͳ3FBDUΛͬͨ w $BOWBTΛ͏͚ͩͳͷͰ7BOJMMB+4Ͱ͍͍͕3FBDUΛͬͨ w )PPLTͷ࿅श͔ͨͬͨ͠ͷͰ3FBDUΛͬͨ
3FBDU)PPLT w ݄ɺ 3FBDU$POGʹͯൃද͞Εͨ3FBDUͷ৽͍͠"1*܈ w 4UBCMFͰ͏ ͜ͱ͕Ͱ͖ͣnpm i react@next͢Δ͜ͱͰ ࣮ࡁΈϦ
ϦʔεΛΠϯε τʔϧͰ͖Δ
3FBDU)PPLT w ͔ͭͯ3FBDUͷίϯϙʔωϯ τ class Something extends React.Component ͷΑ ͏ʹΫϥεͱ
ͯ͠هड़͢Δ͔ SFDPNQPTFΛͬͯ)JHIFSPSEFS$PNQPOFOU )0$ ͱͯ͠هड़ͨ͠ w )0$ͱίϯϙʔωϯ τΛҾͱ ͯ͠ίϯϙʔωϯ τΛฦؔ͢ͷ͜ͱ w ͭ· Γ Ϋϥεͱͯ͠Ͱͳ͘ɺ ؔͱ ͯ͠هड़͢Δͱ͍͏ ͜ͱ
3FBDU)PPLT w SFDPNQPTFͷ࡞ऀ͕'BDFCPPLʹࢀՃͨ͠ w SFDPNQPTF͕ղܾ͠Α ͏ ͱ ͍ͯͨ͠Λ 3FBDUຊମͰ݁ͯ͠վળͰ͖ΔΑ ͏ʹͳͬͨ
w ͦ͏ͬͯੜ·Εͨͷ͕)PPLT w SFDPNQPTFσΟ είϯͱͳͬͨ
ͳͥΫϥεͰμϝ͔ w ΫϥεUIJTʹঢ়ଶΛ࣋ͨͤΔ͜ͱ͕Ͱ͖Δ ʢεςʔ τϑϧɺ ෭࡞༻ʣ w componentDidMount componentDidUpdateͱ͍ͬͨ
ϥΠ ϑαΠΫϧϝ ιο υʹΑͬͯUIJT͕ॻ͖͑ΒΕ֎෦͔Βͷςε τ͕ࠔ w ϥΠ ϑαΠΫϧϝ ιο υʹɺ ίϯϙʔωϯ τͷ ʮΛඳը͢Δʯ ͱ͍͏Λ͑ͨ ෳࡶͳॲཧ͕ॻ͔Ε͕ͪ ʢGFUDIॲཧͱ͔ʣ w ෳࡶੑ͕૿͢ͱݕূ͕ࠔʹͳΓόά͕૿͑Δ 3FBDUυΩϡϝϯ τͷϞνϕʔγϣϯͷทΑ Γҙ༁ͯ͠Ҿ༻
'VODUJPOBM$PNQPOFOU w 3FBDU)PPLTΛ͏ ͜ͱͰίϯϙʔωϯ τΛؔͱͯ͠هड़ͭͭ͠ ͞Βʹঢ়ଶΛѻ͏ ͜ͱ͕Ͱ͖ΔΑ ͏ʹͳΔ w 3FBDUIPPLTOPUNBHJD
KVTUBSSBZT https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e w ैདྷͷϥΠ ϑαΠΫϧϝ ιο υuseEffect() ͱ͍͏ 3FBDU)PPLTͷҰछΛ͍ɺ ؔͱ ͯ͠هड़͢Δ
%FNP
ίʔ υͷߏ export default function App() { // ͻͨ͢Β useState()
const canvasRef = useRef < HTMLCanvasElement > null; useEffect(() => { // ॳظඳը࣌ॲཧ }, []); useEffect(() => { // ԻූՃ࣌ͷॲཧ }, [notes]); useEffect(() => { // εΫϩʔϧҐஔมߋ࣌ͷॲཧ }, [scrollLeft, scrollTop]); const onDragHorizontalScrollBarKnob = useCallback((ev: React.MouseEvent) => { // ਫฏεΫϩʔϧόʔυϥοά࣌ͷϋϯυϦϯά }, [originXY, mediator]); const onDragVerticalScrollBarKnob = useCallback((ev: React.MouseEvent) => { // ਨεΫϩʔϧόʔυϥοά࣌ͷϋϯυϦϯά }, [originXY, mediator]); const onDragScreen = useCallback((ev: React.MouseEvent) => { // Canvasυϥοά࣌ͷૢ࡞ʢԻූͷมߋʣ }, [scrollBarCoord, currentUuid, originXY, notes]); const onMouseDown = useCallback((ev: React.MouseEvent) => { // CanvasͰͷmousedownϋϯυϦϯά }, [ currentUuid, originXY, notes, scrollBarCoord, isDraggingHorizontalScrollBarKnob, isDraggingVerticalScrollBarKnob ]); const onMouseMove = useCallback((ev: React.MouseEvent) => { // canvasͰͷmousemoveϋϯυϦϯά }, [ currentUuid, originXY, notes, isDraggingHorizontalScrollBarKnob, isDraggingVerticalScrollBarKnob ]); return ( <div className="App"> <canvas onMouseDown={ev => onMouseDown(ev)} onMouseMove={ev => onMouseMove(ev)} ref={canvasRef} width="600" height="400" /> </div> ); }
υϥοάϋϯ υ Ϧ ϯάͷ࣮ݱ w ϚεΫ Ϧ οΫΛͯͦ͠ͷ··ͣ͞υϥ οάͱ͍͏࣮͕ຯʹ͍͠ w
ondragͦ͏͍࣮ͬͨͷͨΊͷΠϕϯ τͰͳ͍ w onmousemoveͰev.button === 1ͷͱ͖ υϥοάͱஅ͢ΔΑ ͏ʹذ
εΫϩʔϧόʔͷϋϯ υ Ϧ ϯά w εΫϩʔϧόʔ͕Ϋ Ϧ οΫ͞Ε͍ͯΔ͔Ͳ͏͔ɺ શͯࣗྗͰ࠲ඪܭࢉ ͠ͳ͚ΕͳΒͳ͍
w ϊ ϒͷࠨ্࠲ඪͱӈԼ࠲ඪΛuseState()Ͱ ֨ೲ͓͖ͯ͠onmousedownͰ ຖճɺ ྖҬ͔ఆ͢Δ
ԻූͷઃஔͱԻූͷมߋ w Ϛεͷ࠲ඪ͔Βx - 5, y - 10ͷҐஔΛجʹۣܗ ʢԻූʣ Λඳը
w Ϛε࠲ඪΛجʹ͢ΔͱԻූ͕ΧʔιϧͰӅΕͯ͠·͍ඇײత w ຖճ66*%Λൃߦͯ͠Իූʹ༩ w mousedown࣌ʹهԱͨ͠66*%͕mousemove࣌ʹ༗ޮͳΒ Իූมߋͱఆ͢Δ w Ϣʔβʹී௨ʹΫ Ϧ οΫͯ͠ υϥ οάͯ͠Δײ֮
ॳظඳը w 3FBDU)PPLTʹuseRef()͕͋ΔͷͰͦΕΛͬͯ$BOWBT3FGΛऔಘ w CanvasRef.currentͰωΠςΟ ϒͳ$BOWBTཁૉͷࢀরΛಘΔ w canvasEl.getContext('2d')ͰίϯςΩε τΛಘ͔ͯΒ$BOWBT"1* ௨ΓʹਐΊΕ0,
3FUJOBରԠ w window.devicePixelRatioͰ3FUJOBͳͲͷഒΛऔಘՄೳ w canvasCtx.scale(dpr, dpr)Ͱഒઃఆ͕Մೳ w fillRect(x * dpr,
y * dpr, width * dpr, height * dpr) ͱ͔ຖճॻ͔ͳ͘ ͯࡁΉ w ߴEQSදࣔ࣌ʹδϟΪʔ͕ग़ͳ͍Α ͏ʹɺ ຐ๏ͷߦΛՃ canvasEl.width *= dpr; canvasEl.height *= dpr; canvasEl.style.width = `${canvasEl.width / dpr}px`; canvasEl.style.height = `${canvasEl.height / dpr}px`;
εΫϩʔϧରԠ w Ϋ Ϧ οΫͰͷԻූඳը࣌ʹ ͋Β͔͡ΊxʹscrollLeftΛɺ yʹscrollTopΛ͢ w εΫϩʔϧόʔͷ υϥ
οά࣌ʹ࠶ඳըॲཧͰ ͯ͢ͷԻූ࠲ඪ͔ΒscrollLeftͱscrollTopΛҾ͍ͯ࠶ඳը w ͨͿΜݱࡏͷ࣮ͷ··Ͱ·ͣ͘ ͯ ཧతʹΫ Ϧ οΫ͞Ε࣮ͨࡍͷ࠲ඪͱϐΞϊϩʔϧશମ͔ΒΈͨԾ࠲ඪΛ ܥ౷ཧ͠ͳ͍ͱɺ ॎԣ֦େॖখͳͲͰࢮ͵
ۤ࿑ͨ͠ ʢ3FBDUฤʣ w useEffect()͕૿͑Δ ΒΉ w Πϕϯ τϋϯ υ Ϧ
ϯάʹԠͨ͡࠶ඳըͷछྨ͕ଟ͍͍ͤ͋Δ͚Ͳ ෳͷuseEffect()ʹΑͬͯίϯϙʔωϯ τ͕ؔංେԽͨ͠ w Իූυϥ οά࣌ͱεΫϩʔϧόʔ ɾ υϥ οά࣌Ͱ࠶ඳըॲཧ͕ҧ͏ w useEffect(cb, [])ͷୈೋҾʹࢀরΛྻڍ͢Δ͜ͱͰ ͦͷࢀর͕มԽͨ͠ͱ͖ͷΈuseEffectΛ࣮ߦ͢Δ͜ͱ͕Ͱ͖Δ ʢuseEffect(() => {}, [scrollLeft]) ͳͲʣ
ۤ࿑ͨ͠ ʢ3FBDUฤʣ w 3FBDUͷϚεૢ࡞࣌ͷϋϯ υ Ϧ ϯάҾMouseEventܕͰͳ͍ w 3FBDUख़࿅ऀʹͨΓલͷ͔ w
SyntheticEventͱ͍͏ܗࣜͰΔͷͰnativeEventऔಘͷͨΊʹ ev.persist(); const nativeEv = ev.nativeEvent; ͷΑ ͏ʹҰ୴persist͢Δඞཁ͕͋Δ w ͜͏ ͠ͳ͍ͱoffsetX offsetY͕औΕͳ͍ͷͰҙ
ۤ࿑ͨ͠ ʢ$BOWBTฤʣ w ͻͨ͢Β࠲ඪܭࢉͱͷઓ͍ͱͳΔ w fillRect()ͳͲͯ͢ͷඳըॲཧޙউͪͳͷͰίʔϧॱͰ݁Ռ͕มΘΔ w ։ൃதԻූ͕εΫϩʔϧόʔΛಥ͖ൈ͚Δͱ͔βϥ w ϨΠϠʔͳΜͯ֓೦ແ͍
ʢؤு࣮ͬͯ͢Δ͔$BOWBTϥούʔϥΠ ϒϥ ϦʹཔΔʣ w ͻͨ͢ΒԚ͍ίʔ υͱ ϒϥβ্ͷखಈσόοάΛ܁Γฦͯ͠ ͧ͜͜ͱ͍͏ ͱ͜ΖͰϦ ϑΝΫλ Ϧ ϯά
ۤ࿑ͨ͠ ʢ$BOWBTฤʣ w 3FBDUͷίϯϙʔωϯ τ͔ؔΒ$BOWBTʹؔ͢Δॲཧ͍ͯ͢ग़ͨ͠ w CanvasMediatorͱ͍͏தؒҕৡ༻ͷγϯάϧ τϯΛ࡞ͬͯ ඳըܥͱ࠲ඪऔಘܥͯͦͬͪ͢ʹ࣮͢ΔΑ ͏
Ϧ ϑΝΫλ Ϧ ϯά w Իූ͚ͩͳΒ؆୯ͩͬͨ w εΫϩʔϧόʔͷ࣮Λ࢝ΊͨลΓ͔Βࠞಱͱ ࢝͠Ίͯ ϒϥβͷΠϯ υ࣮ͷ༷ͱ͔ړΓ࢝Ίͨ w 04ͷΠϯ υγεςϜΛ࣮ͨ͠ਓϚδͰҒେͩͱࢥ͏
ࠓޙ͍͖͍ͬͯͨػೳ w Ϋ Ϧ οΫͯ͠ஔ͍ͨԻූͷҠಈ ɾ আ w Ͳͷۣܗ͕Ϋ Ϧ
οΫ͞Ε͔͕ͨऔΕͦ͏ʹͳ͍ͷͰ εΫϩʔϧόʔͱಉ͡Ͱɺ ͯ͢ྖҬܭࢉͰදݱ͢Δ͔͠ͳ͍͔ wυϥοάͨ͠··$BOWBT֎ʹϚεΛಈ͔ͨ͠ΒࣗಈͰεΫϩʔϧ w ࠲ඪऔΕΔͬΆ͍ɺ ࠶ඳըܭࢉ͕ͨΒ໘ͬΆ͍ w ࣮ࡍʹ࠶ੜϘλϯΛ͚ͯԻΛ໐Β͢ w ເͷ·ͨເ
͜͜·Ͱۤ࿑ͯ͠ࢥͬͨ͜ͱ w "OHVMBSͰେنΞϓϦΛ࡞Εͯ$BOWBTશવ࡞Εͳ͍ w 3FBDU͡Όͳ͘ ͍͍ͯ w $VTUPN&MFNFOUTͱ૬ੑΑͦ͞͏
5IBOLZPV %0.ʹײँ͠ͳ͕Β$BOWBTͰ(6*ͷԞਂ͞ʹ৮ΕΑ ͏ ʂ