èšäºãšãããªã¯ãåŸæ¥ã®çš®é¡ã®ã³ã³ãã³ãã§ãã èè ããã©ãããã©ãŒã ã«åŒãä»ããèŠèŽè ãå¢ããããã®æ°ããããŒã«ãæäŸããããã«ãZenã¯éåžžã®åœ¢åŒãè¶ ããããšã«ããŸããã æ°ãã圢åŒã®1ã€ãç©èªã«ãªããŸããã ããã¯ãå ±éã®ããŒãã«ãã£ãŠçµåãããã«ãŒãã®ã»ããã§ãã ã€ã³ã¿ãŒããããŠãŒã¶ãŒã¯èªãåæ°ãæžããŸãããããã§ãé¢çœãã¹ããŒãªãŒãæã«å ¥ããããšæã£ãŠããŸãïŒããšãã°ããã¬ãçªçµãçããããªãã©ã€ããããŒããã£ã¹ããèŠããªã©ïŒã èè ãäžè²«ããçç·šå°èª¬ãèªã¿ãèªè ã楜ããŸããã®ã«åœ¹ç«ã€ãã©ãŒããããäœæããŸããã
åºç瀟ãšèè ã®ç©èª
ã«ãŒãã«ã¯ãããã¹ãããªã³ã¯ãç»åããããªãGIFãå«ããããšãã§ããŸãã ç©èªã¯ç©èªãèªãã段éçãªæ瀺ãã¬ã·ããæäŸããæçšãªæžç±ã®ãªã¹ããçºè¡ããäºç®ç®¡çã¢ãããŒãã®é·æãšçæã説æããããšãã§ããŸãã ããã¯ãèå³æ·±ãã³ã³ãã³ããäœæãããé·ãããã¹ããæžããªãèè åãã®åœ¢åŒã§ãã
åºæ¬çã«ããã®åœ¢åŒã¯æºåž¯é»è©±ã«çŠç¹ãåœãŠãŠããŸããå€ãã®å Žåã人ã ã¯ã¢ãã€ã«ããã€ã¹ããæ å ±ããšã³ã¿ãŒãã€ã¡ã³ãã³ã³ãã³ããæ¶è²»ããŸãã å¶éãè¿œå ããŸããã圢åŒã¯å®¹éã倧ããã¯ãã§ãããçããããç©èªã«ãŒãã®æ°ã¯ç¡éã§ã¯ãããŸããã åã«ãŒãã«ã¯æ倧1ã€ã®ãããªãš1ã€ã®ãªã³ã¯ãå«ãŸããŠãããããèªè ã®æ³šæãé床ã«ãããããšãªããç©èªãé çªã«å®è¡ã§ããŸãã èå³ã®ãã人ã¯ãç©èªããèè ã®ãŠã§ããµã€ãã«ã¢ã¯ã»ã¹ããŠãè³æã®æ¡åŒµçãèªãããšãã§ããŸãããç©èªã®å 容ã¯ãããã¯ãç解ããã®ã«ååãªã¯ãã§ãã
äŸïŒç©èªã®ç©èª
ç©èªã®æãè¿ãé¡äŒŒç©ã§ããInstagramã®ã¹ããŒãªãŒã¯ãæéã«å¶éãããã24æéã ã衚瀺ãããŸãã ããã¯ã³ã³ãã³ãã«åœ±é¿ãäžããŸãïŒçŽ æã¯ãå ±éã®ããŒããæ å ±äŸ¡å€ã®ãªãã瀟äŒççžäºäœçšã芪ãã人ããã®åå¿ãåãåãããšã«ãã£ãŠé¢é£ä»ããããŠããªãå ŽåããããŸãã ç§ãã¡ã¯ã¹ããŒãªãŒã奜ãã§ãããšããäºå®ã«ããããããããã®åœ¢åŒã¯Zenã«ã¯é©ããŠããŸããã ç§ãã¡ã®åºçç©ã¯ã¯ããã«é·ã衚瀺ãããå€ãã®å Žåãåã瀟äŒçãŸãã¯å°ççã°ã«ãŒãã«å±ããªãèŽè¡ã«æšå¥šãããŸãã ãã€ã¯ããã©ãŒãããã®äœ¿ãããããšãé·ãèªã¿åãã®é¢äžãšã¹ããŒãªãŒã©ã€ã³ãçµã¿åããããã©ãŒããããæ§ç¯ããŸããã
ãŠãŒã¶ãŒã«å€æ§ã§ãŠããŒã¯ãªç©èªãäœæããæ©äŒãæäŸããããã«ããã¬ãŒã³ããŒã·ã§ã³ãäœæããããã°ã©ã ã®ãããªã³ã³ãã³ãã®ã¬ã€ã¢ãŠããšãã¶ã€ã³ã®ããã®ããŒã«ãåããç¹å¥ãªãšãã£ã¿ãŒããŠãŒã¶ãŒã«æäŸããå¿ èŠããããŸããã ãšãã£ã¿ãŒã¯ããã¬ãŒã³ããŒã·ã§ã³ãèŠèŠçã«é åçã«ããæ¹æ³ãã¬ããŒã圢åŒã®å¶éãããã³äœ¿ãããããäœæè ã«ä¿ãå¿ èŠããããŸããã ãã®ãããèªè ã«è¡šç€ºãããç©èªã衚瀺ããã衚瀺ã¢ãŒããè¿œå ããŸããã èè ãèŠçŽ ã®é 眮ã®ãã¿ãŒã³ã«éå®ããŸããã§ããïŒç©èªã«ãŒãäžã®ãã¹ãŠã®èŠçŽ ã¯ä»»æã«é 眮ã§ããŸãã ããã«ãçžäºã®èŠçŽ ã®éãªããå¶åŸ¡ã§ããã¬ã€ã€ãŒã·ã¹ãã ãéçºããŸããã
ç©èªãšãã£ã¿ãŒ
ãšãã£ã¿ãŒãäœæããéçšã§ãå€ãã®èå³æ·±ãæè¡çãªåé¡ã«çŽé¢ããŸããã ãã®èšäºã§ã¯ããããã®è§£æ±ºæ¹æ³ã«ã€ããŠèª¬æããŸãã
䜿çšã¹ã¿ãã¯
ãã¯ãããžãŒããŒã¹ã¯ãReactïŒãšãã£ã¿ãŒçšïŒãpreactïŒè¡šç€ºçšïŒãReduxãDraft.jsïŒããã¹ããããã¯çšïŒãããã³ãããŒã¿ã€ãã§æ§æãããŠããŸããã ç¶æ ã¯æ£èŠåããã圢åŒã§ä¿åããïŒnormalizrãåç §ïŒãæãäžè¬çãªæäœïŒã«ãŒãã®èŠçŽ ã®ããããã£ã®æŽæ°ïŒããã°ããå®è¡ã§ããããã«ãªããŸããã ä»ã®ã¢ã¯ã·ã§ã³ïŒã«ãŒãã®äº€æããããã¯ã®è¿œå ãåé€ãªã©ïŒã®å Žåãæ£èŠåãããç¶æ ã¯ããªããžã§ã¯ãããªãŒã®åœ¢ã§éåžžã®ããŒã¿ã¹ãã¬ãŒãžãããåªããããã©ãŒãã³ã¹ã瀺ããŸãã
ã«ãŒãã®ã«ãŒããšãããã¯ãã¢ãããã£ãã«ãã
æåã®ã¿ã¹ã¯ã¯ãä»»æã®ãµã€ãºã§æ§å³ãä¿æããé©å¿ã«ãŒããäœæããããšã§ããã ã¢ãã€ã«ãã©ãããã©ãŒã ã§ã¯ãã«ãŒãã¯ã¢ã¹ãã¯ãæ¯ãèæ ®ããŠæ倧é åãå æããããšããããããã®å¯žæ³ã¯ããã€ã¹ããšã«å€§ããç°ãªãå¯èœæ§ããããŸãã
ãããã£ãŠïŒ
- ã«ãŒãã¯ãä»»æã®ç»é¢ãµã€ãºã§æå®ãããã¢ã¹ãã¯ãæ¯ïŒ44:75ãéžæïŒãä¿åããŸãã
- ã«ãŒãäžã®ããã¹ãã¯ãã©ã®ãµã€ãºã®ã«ãŒãã§ãåãçžå¯Ÿçãªå æé åãä¿æããŸãã ã€ãŸãããã©ã³ããµã€ãºã¯ã«ãŒãã®ãµã€ãºã«æ¯äŸããå¿ èŠããããŸãã
- ãããã¯ã¯ãã©ã®ãµã€ãºã®ã«ãŒãã§ãçžå¯Ÿçãªãµã€ãºãšå Žæãä¿æããŸãã
ãããã®èŠä»¶ãå®è£ ããæ¹æ³ãæ€èšããŠãã ããã
ã«ãŒãã®ã¢ã¹ãã¯ãæ¯ãç¶æããæ¹æ³ã¯ïŒ
ãŸããçŽç²ãªCSSã䜿çšãããã£ãã 確ãã«ããããã¯ãŒã¯ã«ã¯ãããå¯èœã«ããããã€ãã®æ¹æ³ãèšè¿°ãããŠããŸãã
- ãããã¯å¹ ã®çžå¯Ÿå€ãååŸããããããããŒã»ã³ããŒãžã§èšå®ãããããã£ã³ã°ããããã£ã䜿çšããããã£ã³ã°ã«ãã寞æ³èšå ¥ ã ãã®æ¹æ³ã¯ãã«ãŒããç»é¢ã«ãå ¥åãããããšãã§ããªãããé©åããŸããã§ããã ã€ãŸããã«ãŒãã®é«ããç»é¢ã®é«ããè¶ ããŠããã«ãŒãã®é«ãã¯æžå°ããããã®æ¯çãç¶æãããŸãã
- vhãšvwã§æå®ãããé«ããå¹ ãæ倧é«ããæå€§å¹ ã®çµã¿åããã§ãµã€ãºãèšå®ãããšãç®çã®å¹æãåŸãããšãã§ããŸãã ãã ãããã®æ¹æ³ã¯ç»é¢ãµã€ãºã«ãã£ãŠå¶éãããŸãã ã€ãŸããã«ãŒããç»é¢å šäœãå æããªãã¬ã€ã¢ãŠãã«ã«ãŒããåã蟌ãå ŽåïŒããšãã°ããšãã£ã¿ãŒå ïŒãã¢ã¹ãã¯ãæ¯ã¯ä¿åãããŸããã
ãããã£ãŠãçŽç²ãªCSSãœãªã¥ãŒã·ã§ã³ãæŸæ£ããå¿ èŠãããããã®çµæãCSSãœãªã¥ãŒã·ã§ã³ãããã¯ããã«ã³ã³ãã¯ãã§ç解ããããããšãå€æããJSãœãªã¥ãŒã·ã§ã³ã䜿çšãããŸããã
// @flow type Size = { width: number, height: number }; function getFittedSlideSize(container: Size, target: Size): Size { const targetAspectRatio = target.width / target.height; const containerAspectRatio = container.width / container.height; // if aspect ratio of target is "wider" then target's aspect ratio const fit = targetAspectRatio > containerAspectRatio ? 'width' // fit by width, so target's width = container's width : 'height'; // fit by height, so target's height = container's height return { width: fit === 'width' ? containerWidth : Math.round(containerHeight * ( target.width / target.height)), height: fit === 'height' ? containerHeight : Math.round(containerWidth * (target.height / target.width)), }; }
ã¬ã³ããªã³ã°é床ã«ãã€ãã¹ã®ãã€ãã¹ã¯ãããŸãããå éã®å¯èœæ§ããããŸãã ããšãã°ãã¡ã€ã³ã®JSãã³ãã«ããé 眮ãåé€ããã«ãŒãã®HTMLã³ãŒãã®çŽåŸã«é 眮ãå®è¡ã§ããŸãã ãã®åŸãã«ãŒãã¯ããã«æ£ãããµã€ãºã§è¡šç€ºãããŸãã
ã«ãŒãã®å²åã¯ã©ã®ç»é¢ã§ãä¿åãããŸã
ããã¹ãèŠçŽ ã®çžå¯Ÿçãªãµã€ãºãä¿åããæ¹æ³ã¯ïŒ
ã¹ã©ã€ãå ã®ããã¹ãèŠçŽ ã®ãµã€ãºãæ¯äŸçã«å€æŽããããã«ã次ã®ããšãè¡ããŸããã
- ããã¹ãèŠçŽ ã®ãµã€ãºã¯ãã¹ãŠemã§æå®ãããŸãã
- ã¹ã©ã€ãã®å Žåããã©ã³ããµã€ãºã¯pxã§èšå®ããã次ã®äœçœ®ããååŸããæ¯çã§èšç®ãããŸãã
- ã¹ã©ã€ãã®ããŒã¹å¹ ïŒBASE_WIDTHïŒã320pxã«ããŸãã
- ã¹ã©ã€ãã®ããŒã¹å¹ ã®åºæ¬ãã©ã³ããµã€ãºïŒBASE_FONT_SIZEïŒã16pxã«ããŸãã
- 次ã«ãã¹ã©ã€ãã®ãµã€ãºãå€æŽãããšãæ°ãããã©ã³ããµã€ãºã次ã®ããã«èšç®ãããŸãã
const relativeFontSize =ïŒBASE_FONT_SIZE * slideSize.widthïŒ/ BASE_WIDTH;
ãããã£ãŠãemã§ãã©ã³ããµã€ãºãèšå®ãããšãèŠçŽ ã®ãã©ã³ããµã€ãºãèªåçã«åèšç®ãããŸãã
ã«ãŒãäžã®ãªããžã§ã¯ãã«äœçœ®ãšçžå¯Ÿçãªãµã€ãºãä¿æãããæ¹æ³ã¯ïŒ
æ§æãä¿æããã«ã¯ãçžå¯Ÿåº§æšç³»ã®å°å ¥ãæé©ã§ãã Webãã©ãããã©ãŒã ã®ãããã§ããã®ãããªã·ã¹ãã ã¯ãã§ã«ååšããŸã-ããã¯ããããã¯ã®ãµã€ãºãšå ŽæãããŒã»ã³ãã§æå®ããä»äºã§ãïŒ å®éããã¯ã»ã«åäœã®ã«ãŒãã®ãµã€ãºã«ããããããããŒã»ã³ããŒãžã§èšå®ããããªããžã§ã¯ãã®ãµã€ãºãšå Žæã«ããããªããžã§ã¯ãã¯æ¯äŸçã«å€åããŸãã
å軞ã«0ã100ïŒ ã®å¯èŠé åãæã€åã«ãŒãå ã«æ°ãã座æšç³»ïŒãã«ãŒããïŒãå°å ¥ããããšãããããŸããã 次ã«ããã¹ãŠã®ãã¯ã»ã«ãµã€ãºãããŒã»ã³ããŒãžã«å€æããæ¹æ³ãåŠç¿ããå¿ èŠããããŸãã ããã¯ã次ã®å Žåã«å¿ èŠã«ãªããŸãã
- 1ã€ã®è»žã®å¯žæ³ãšå ã®å¯žæ³ã«é¢ããç¥èã«åºã¥ããŠããªããžã§ã¯ãã®ãµã€ãºãèªã¿åããŸãã ããšãã°ãã¹ã©ã€ãã«ç»åãæ¿å ¥ããå Žåãããã©ã«ãã®90ããŒã»ã³ãã®å¹ ãèšå®ããããŒã»ã³ãã§é«ããèšç®ããå¿ èŠããããŸãã
- ã«ãŒãäžã®ãªããžã§ã¯ãã移åããŸãã
- ãµã€ãºãå€æŽããŸãã
ãµã€ãºãäžæãªãªããžã§ã¯ãã®åæå
çŸåšããã«ãŒãã座æšç³»ããããããã«ãŒãã®ãµã€ãºãå€æŽãããšãã«çžå¯Ÿçãªäœçœ®ãæªãããšãå¿é ããããšãªããã«ãŒãã«ãããã¯ãé 眮ã§ããŸãã
åãããã¯ã«ã¯ããããã¯ã®ãµã€ãºãšå Žæãèšè¿°ãããžãªã¡ããªããããã£ããããŸãã
{ geometry: { x: number, y: number, width: number, height?: number } }
ã¢ã¹ãã¯ãæ¯ãåºå®ããããããã¯ïŒããšãã°ãç»åããããªïŒãè¿œå ãããšããã¯ã»ã«åº§æšç³»ãããã«ãŒãããŸã§ã®ãµã€ãºãåèšç®ããéã«åé¡ãçºçããŸãã
ããšãã°ãã¹ã©ã€ãã«ç»åãè¿œå ããå Žåãããã©ã«ãã¯ãã«ãŒãã座æšç³»ã®èŠçŽ ã®å¹ ã®90ïŒ ã«èšå®ãããŸãã ç»åã®å ã®å¯žæ³ïŒImage.naturalWidthããã³Image.naturalHeightïŒããã«ãŒããã¯ã»ã«ãã®å¯žæ³ãããã³æ°ãã座æšã§ã®ç»åã®å¹ ãããã£ãŠããå Žåãé«ãïŒæ°ãã座æšã§ãïŒãèšç®ããå¿ èŠããããŸãã é«åºŠãªç®è¡ã®ç¥èã«é Œã£ãŠããã«ãŒãã座æšç³»ã®èšç®é¢æ°ãæšæž¬ããŸããã ããšãã°ãåçã®é«ããèšç®ã§ããŸãã
function getRelativeHeight(natural: Size, container: Size, relativeWidth: number) { return (natural.height / natural.width) * (container.width / container.height) * relativeWidth; }
ããã§ãèªç¶ã¯ãã¯ã»ã«åäœã®ç»åã®ãµã€ãºãã³ã³ããã¯ãã¯ã»ã«åäœã®ã¹ã©ã€ãã®ãµã€ãºãrelativeWidthã¯ããŒã»ã³ãåäœã®ç»åã®ãµã€ãºã§ãã
ãªããžã§ã¯ãã®åã
ãã«ãŒãã座æšç³»ãžã®å€æãç¿åŸãããšããªããžã§ã¯ãã®åããç°¡åã«èªèã§ããããã«ãªããŸããã ãããæ åœããã³ãŒãã¯æ¬¡ã®ãããªãã®ã§ãã
type Size = {width: number, height: number}; type Position = {x: number, y: number}; class NarrativeEditorElement extends React.Component { // ... handleUpdatePosition = (e) => { // slide - DOM-, const {slide} = this.props; if (!this.state.isMoving) { // this.ref â DOM- (, ..) this.initialOffsetLeft = this.ref.offsetLeft; this.initialOffsetTop = this.ref.offsetTop; } const relativePosition = getRelative( {width: slide.offsetWidth, height: slide.offsetHeight}, {x: this.initialOffsetLeft + e.deltaX, y: this.initialOffsetTop + e.deltaY}, ); this.setState({ geometry: { ...this.state.geometry, x: relativePosition.x, y: relativePosition.y, }, isMoving: true, }); } // ... } function getRelative(slideSize: Size, position: Position) { return { x: 100 * position.x / slideSize.width, y: 100 * position.y / slideSize.height, }; }
4ãã€ã³ãã®ãµã€ãºå€æŽ
é©åãªããžã¥ã¢ã«ãšãã£ã¿ã§ã¯ãå¢çç·ã®è§ã«ãããæ£æ¹åœ¢ãããã©ãã°ããŠããªããžã§ã¯ãã®ãµã€ãºãå€æŽã§ããŸãã ãã®æ©äŒãå®çŸããå¿ èŠããããŸããã
ãŠãŒã¶ãŒãåŒã£åŒµã£ãŠããè§åºŠã«å¿ããŠãªããžã§ã¯ãã®ãµã€ãºå€æŽãåŠçããã³ã³ãã¯ãã§ããããããã³ãŒããæžãããšã¯ããã»ã©ç°¡åã§ã¯ãããŸããã§ããã 決å®ãããµã€ã¯ãªã³ã°ãããåã«ãäžè¬çãªã©ã€ãã©ãªã§ãããã©ã®ããã«è¡ããããã確èªããŸããã ããšãã°ã jQuery UIã®ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
ã³ãŒãã¯ã³ã³ãã¯ãã«èŠããŸãããç解ã¯å®¹æã§ã¯ãããŸãããé¢æ°ã¯ãã¯ãªãŒã³ãã§ã¯ãªããã¯ã©ã¹ãšãã®ããããã£ã®å€æ°ã®å éšã¡ãœããã䜿çšãããé¢æ°ã®å®è¡ã®ã³ã³ããã¹ããéèŠã§ãïŒé©çšãåç §ïŒã
ãã®ãããžã§ã¯ãã§ã¯ãã»ãŒåãã³ãŒãã次ã®ããã«èšè¿°ãããŠããŸã ã ããã§ã¯ããªããžã§ã¯ãã®æå°ãµã€ãºãšã¢ã¹ãã¯ãæ¯ã®ç¶æã«é¢ãããªãã·ã§ã³ã®å¶éïŒpreserveAspectRatioïŒãè¿œå ã§èæ ®ãããŸããããã¯ããããªãŸãã¯ç»åã®ãµã€ãºãå€æŽãããšãã«éèŠã§ãã
ã³ãŒããã³ã³ãã¯ããšåŒã¶ããšã¯ã§ããŸããããé¢æ°ã¯ãã¯ãªãŒã³ãã§ããããšãå€æãããœãªã¥ãŒã·ã§ã³èªäœã®æ§é ã¯åçŽã§ããã
芪æãªãèªè ã®çãããããã®åé¡ã解決ããã³ãŒãã®ããŒãžã§ã³ãææ¡ããŠããããçŽ æŽããããšæããŸãã ã©ã®ã³ãŒããéåžžã«çãç解ãããããªãããç解ããåŸãç¹å®ã®ãã¿ãŒã³ãããããšãèªããŸãã
ç°ãªããã©ãããã©ãŒã ã§ã®äžè²«æ§ã®ãªãããã¹ãã¬ã³ããªã³ã°ã®åé¡
ç©èªã®è¡šç€ºã®å€ããå°ãªãã倧èŠæš¡ãªãã¹ããéå§ãããåŸãåããã©ã³ãããµã€ãºããã®ä»ã®å±æ§ãæã€åãããã¹ããç°ãªããã©ãããã©ãŒã äžã§ç°ãªãè¡æ°ãæã£ãŠããããšãããã£ãŠé©ããïŒ
ããšãã°ãSafariã§ã¯ããã©ãã£ããäœæãããšãã«äžéšã®ããã¹ããããã¯ã«4è¡ãå«ãŸããŠããŸããããAndroidã®Chromeã§è¡šç€ºãããš3è¡ã衚瀺ãããŸããã ãã®åäœã®æ£ç¢ºãªçç±ã¯ããããŸããã§ããããããŸããŸãªãã©ãããã©ãŒã ã®ããã¹ãã¬ã³ããªã³ã°ãšã³ãžã³ã®æ©èœãåå ã§ããã
å ¬éåã«ããã¹ããããã¯ãè¡ã«åå²ããããšã§åé¡ã解決ããŸããã ãããŠãããã«ãèå³ã®ããå ŽæããããŸããã æååãå®çŸ©ããæåã®ã¢ãããŒãã¯ãåæåã<span>ã§ã©ããããgetBoundingClientRectã䜿çšããŠãã®äœçœ®ã決å®ããããšã§ããã ããã¯ããã«æ©èœããããªãé·ãéããã®ã¢ãããŒããããããåé¡ã«æ°ä»ããªãã£ãã åé¡ãäœã§ãããšæããŸããïŒ
Yandex Sans Textãå«ãå€ãã®ãã©ã³ãã«ã¯ãäžéšã®æåã®çµã¿åããïŒã«ãŒãã³ã°ïŒã®ã·ã³ãã«éè·é¢ã衚瀺ããããã®æé©åãå«ãŸããŠããããšãããããŸããã
CSSã«ã©ã ããããã£font-kerningïŒå³åŽã®ã«ã©ã ã«ã¯äœãèšå®ãããŠããŸãã
åæåã<span>ã§ã©ãããããŠããå Žåããã®æé©åã¯æ©èœããŸããïŒ ç€ºãããçµã¿åããã¯ããããåæåã®åšãã«<span>ã¿ã°ããªãïŒã€ãŸãããšãã£ã¿ãŒãŠãŒã¶ãŒã«è¡šç€ºãããïŒæååã¯ãã¿ã°ãããå ŽåãããçãããšãããããŸãã
å€ä»£ã®CSSããããã£font-kerningïŒnoneã«ããããã®åé¡ããã°ãã解決ã§ããŸãããããã¯ããããã®æé©åãç¡å¹ã«ããã ãã§ãã ãããããç©èªãèŠãŠããã»ãšãã©ã®äººã¯äœã«ãæ°ä»ããªãã§ãããã
ãããããã¹ãŠãçŸããããæ¹æ³ãå¿ èŠã§ãïŒ ãŸããç¹å®ã®ç¯å²ã®ããã¹ãéžæã«å¯ŸããŠgetBoundingClientRectïŒïŒãšåæ§ã®æ å ±ãæäŸã§ãããåãå€ä»£ã®éåžžã«äŸ¿å©ãªRange APIã䜿çšãããœãªã¥ãŒã·ã§ã³ãèŠã€ããŸããã çŸåšããã®ãœãªã¥ãŒã·ã§ã³ã«åãçµãã§ãããè¿ãå°æ¥ãæ¬çªç°å¢ã«ç§»è¡ããããšãæåŸ ããŠããŸãã
ããã¹ãèŠçŽ ã®äžã«é£ããã¢ã³ããŒã¬ã€
å€ãã®èè ãåéæã®ç»åã䜿çšããŠãåçã®äžã«é 眮ããããã©ã³ãã®ã³ã³ãã©ã¹ããé«ããŸããã ä»ã®äººãã¡ã¯ããšãã£ã¿èªäœã«é©åãªæ©èœãè¿œå ããããã«äŸé ŒããŸããã
ãã¶ã€ããŒã®ã¢ãŒãã£ã¯ãåºæ¿ãžãªã¡ããªã®æãé£ããããŒãžã§ã³ãéžæããããšã§éçºãé©ãããŸããã åæ§ã®é·ãã®ç·ã1ã€ã®é·æ¹åœ¢ã«çµåããããšã«å ããŠã察称軞ãšããŠäœåãªèŠçŽ ïŒããšãã°ããaããŸãã¯ãoãïŒãªãã§å°æåã®äžå€®ã䜿çšãããšããã¢ã€ãã¢ãçãŸããŸããã ãã®ãããªå®è£ ã¯ãçµæã®å³ã®ã挫ç»ãã®åŒ·åãããå¹æãäœæããŸã-ãããã¯æŒ«ç»ã®å¹ãåºãã«äŒŒãŠããŸãã
åºæ¿ã®ã¢ã«ãŽãªãºã ãšå®è£
æåŸã®æ®µéã§èšç®ãããç·ã®å¯žæ³ã䜿çšããŠãæåã§å³ãæãå¿ èŠããããŸããã ãããã¯ãåãååŸã®å匧ãšçŽç·ã§æ§æãããéããsvgãã¹ãšããŠå®è£ ãããŸãã
æ¢ç¥ã®æè¡ã¯ããããåé¡ã®è§£æ±ºã«é©ããŠããªããããã«ããŒã«äœ¿çšãããsvgæ²ç·ãã¬ã³ããªã³ã°ããç¬èªã®ã¢ã«ãŽãªãºã ãäœæããŸããã
ãããã«
ç©èªã¯æ°ãã圢åŒã§ãããéçºããå¿ èŠããããŸãã ã¹ããŒãªãŒãžã®ããè¯ãé¢äžã®ããã«ããã©ãã£ãã«ãŒãã®é åãå¢ãããã°ã©ãã£ãã¯èŠçŽ ãšã¢ãã¡ãŒã·ã§ã³ãè¿œå ãããžã§ã¹ãã£ã®äœ¿çšããµããŒãããåæ§ã®ãã©ãã£ãããã·ãŒã ã¬ã¹ãã«è¡šç€ºã§ããããã«ããŸãã
èªè ã¯åºçç©ã®å質ãé«ãè©äŸ¡ããŠããŸãã åºçç©ãããè¯ãããããã«ããªãŒãã£ãšã³ã¹ã奜ããªãã®ãèè ã«äŒããŸãã äžéšã®èè 㯠ãèªåã®æèŠãšåªããç©èªãäœæããæ¹æ³ãæ¢ã«å ±æããŠããŸãã
æè¡çãªèŠ³ç¹ããã¯ãæªè§£æ±ºã®åé¡ãšæé©åã®ç¯å²ããããŸããã ããšãã°ãAndroidã®äžéšã®çµã¿èŸŒã¿ãã©ãŠã¶ãŒïŒéåžžã¯ãã³ããŒèªäœã®ãã©ãŠã¶ãŒïŒã§ã¯ãã·ã¹ãã ãã©ã³ããå¢ãããšãWebããŒãžã®ãã©ã³ããµã€ãºãç¹å®ã®ãããå€ä»¥äžã«èšå®ããããšã匷å¶ãããŸãã ç©èªã®å Žåãããã¯ãã¡ããæ§å³ãå£ããŸãã
iOSããã³Androidã§ã®ãã¬ãŒã¿ãŒãã¥ãŒã¢ãŒã®ãã€ãã£ãå®è£ ãèšç»ãããŠããããããã®ãããªãã¥ãŒã¢ãŒã®äœæãç°¡çŽ åããå¯èœæ§ãæ€èšããŠããŸãã èå³æ·±ãæ¹æ³ã®1ã€ã¯ãã¹ã©ã€ãäžã®åã ã®èŠçŽ ã®ãã¹ã¯ãªãŒã³ã·ã§ãããã§ããããã«æãããŸãã ãããã¯æ£ãããã©ã³ããµã€ãºãèããªãããã«ããŸããåçã¯ãããã¹ããšã¯ç°ãªãããã«ãŒãã座æšç³»ã®å²åã«ãããµã€ãºãéåžžã«èªç¶ã«å€åããŸãã ããã«ãYandexãã©ã³ããããŠã³ããŒãããå¿ èŠã¯ãŸã£ãããããŸãããããã¹ãçŽ æã®ã¬ã³ããªã³ã°ãªã©ããããããã¢ã«ãŽãªãºã ã䜿çšããå¿ èŠããããŸããã
æåŸã«ãã¹ããªãŒã ïŒæåã¯ãããªãã¹ããªãŒãã³ã°ããããã®åªããã€ã³ãã©ã¹ãã©ã¯ãã£ïŒããéåžžã®MP4 / WebMãã¡ã€ã«ã«ãããªã転éããäºå®ã§ããçããããªã§ã¯ããã®ã¢ãããŒãã¯ããè¯ãäºææ§ãšé床ã瀺ããŸãã
ãã®èšäºã¯Yandex.Zenã®ã¹ã¿ããã«ãã£ãŠäœæãããŸãããDmitryDushkinãšVasily Gorbunovã¯ãããã³ããšã³ãã®Ulyana Salo-ãã¶ã€ã³ã«ã€ããŠæžããŸããã