Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Canvasでピアノロールを作る Canvasでスクロールを扱う際の 座標計算と苦労 / ng...
Search
OKUNOKENTARO
January 18, 2019
Technology
1.3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Canvasでピアノロールを作る Canvasでスクロールを扱う際の 座標計算と苦労 / ng-kyoto Angular Meetup #9
2019/1/18、ng-kyoto Angular Meetup #9 にて発表した資料です。
OKUNOKENTARO
January 18, 2019
More Decks by OKUNOKENTARO
See All by OKUNOKENTARO
トレタO/X アーキテクチャ移行記 Next.js App Router化への道のり / TORETA TECH UPDATE 1
okunokentaro
5
12k
Podcastを継続する技術 / refactoradio-240119
okunokentaro
1
240
Webアプリケーション設計の第一歩は ディレクトリの整理から / Encraft 1
okunokentaro
33
10k
JSONとJSON Schemaを改めて理解する / tokyo_study
okunokentaro
9
2.5k
それでもどうしてRecoilを使うのか / Harajuku.ts Meetup Recoil
okunokentaro
19
5.7k
TypeScriptは10年でこんなに進化しました / TechFeed Experts Night 11
okunokentaro
6
1.8k
Hasura.io RDBをサクサク作る方法はARやO/RMだけじゃなくなりました/hasura-io
okunokentaro
5
730
コードには型アノテーションよりも要件アノテーションを増やせ!/harajukuts2
okunokentaro
14
6.6k
10年と3ヶ月でWebサービスを作った話 / Piyogrammer Conference 2021
okunokentaro
2
1.1k
Other Decks in Technology
See All in Technology
AI時代に必要な脅威モデリング― 変化の速度に負けない理解とリスク判断
masakane55
5
1.2k
AIは爆速なのに、私が詰まっていた話 ― 音声入力と鳴くマスコットでボトルネックを削る
yama3133
0
570
1万名の社員が使う認証基盤で どう信頼性を担保するか?
kairim0
0
220
3つのアプローチで目指す チームを強くするAI駆動開発
thkt
0
140
"優秀な誰か"の下位互換にならないために
yut0naga1_fa
0
1k
味覇で作るパスタが美味い - 20261001_yabaubuki.dev
livesense
PRO
0
110
AI 時代の Azure エンジニアリング ~ 私たちは何を磨き、何を任せるのか ~
chack411
1
550
Deep Data Security 機能解説
oracle4engineer
PRO
2
740
SDDの運用にめげずに向き合った話
sansantech
PRO
1
140
ビジネスを止めない技術的負債の返済のための戦略とその手法 - 技術的負債と向き合う / Complexity and Simplicity
soudai
PRO
3
680
継続的なAIコスト最適化
bgpat
1
270
全人類(ほぼ)AWS Organizations の上でAWSを利用している、その世界を知る話
htan
1
130
Featured
See All Featured
The Language of Interfaces
destraynor
162
27k
Design in an AI World
tapps
1
350
Designing for humans not robots
tammielis
254
26k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
510
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
260
Designing for Timeless Needs
cassininazir
1
520
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.3k
How to make the Groovebox
asonas
2
2.5k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Building the Perfect Custom Keyboard
takai
2
900
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*ͷԞਂ͞ʹ৮ΕΑ ͏ ʂ