ãã®è¨äºã§ã¯ããã¥ã¼é·ç§» API ãã©ã®ããã«åä½ããã®ãããã¥ã¼é·ç§»ã使ããé·ç§»ã¢ãã¡ã¼ã·ã§ã³ãã«ã¹ã¿ãã¤ãºããæ¹æ³ãã¢ã¯ãã£ããªãã¥ã¼é·ç§»ãæä½ããæ¹æ³ã«ã¤ãã¦ã®çè«ã説æãã¾ããåä¸ãã¼ã¸ã¢ããªã±ã¼ã·ã§ã³ (SPA) ã«ããã DOM ç¶æ ã®æ´æ°ã¨ãè¤æ°ãã¼ã¸ã¢ããªã±ã¼ã·ã§ã³ (MPA) ã«ãããææ¸éã®ç§»åã®ä¸¡æ¹ã«ããããã¥ã¼é·ç§»ãã«ãã¼ãã¦ãã¾ãã
ãã¥ã¼é·ç§»ã®ããã»ã¹ãã¥ã¼é·ç§»ãåä½ããããã»ã¹ã追ã£ã¦ã¿ã¾ãããã
ãã¥ã¼é·ç§»ãçºçãã¾ããã©ã®ããã«è¡ããããã¯ããã¥ã¼é·ç§»ã®ç¨®é¡ã«ãã£ã¦ç°ãªãã¾ãã
document.startViewTransition()
ã¡ã½ããã®ã³ã¼ã«ããã¯ã¨ãã¦æ¸¡ãã¾ãã@view-transition
ã¢ããã«ã¼ã«ãè¨è¿°ããnavigation
è¨è¿°åã auto
ã«è¨å®ãããã¨ã§ããã¥ã¼é·ç§»ã«åæããå¿
è¦ãããã¾ãã
ã¡ã¢: ã¢ã¯ãã£ããªãã¥ã¼é·ç§»ã¯ãé¢é£ãã ViewTransition
ã¤ã³ã¹ã¿ã³ã¹ãä¿æãã¦ãã¾ãï¼ä¾ãã°ãå䏿æ¸å
(SPA) ã®é·ç§»ã®å ´åãstartViewTransition()
ã«ãã£ã¦è¿ããã¾ãï¼ãViewTransition
ãªãã¸ã§ã¯ãã«ã¯ãããã¤ãã®ãããã¹ãå«ã¾ãã¦ããããã¥ã¼é·ç§»ããã»ã¹ã®ãã¾ãã¾ãªæ®µéã«å°éããéã«ãããã«å¯¾å¿ããã³ã¼ããå®è¡ãããã¨ãã§ãã¾ãã 詳ããã¯ãJavaScript ã«ãããã¥ã¼é·ç§»ã®å¶å¾¡ãåç
§ãã¦ãã ããã
ç¾å¨ã®ï¼å¤ããã¼ã¸ï¼ãã¥ã¼ã§ã¯ãAPI 㯠view-transition-name
ã宣è¨ãããè¦ç´ ã®ã¹ãããã·ã§ãããåå¾ãã¾ãã
ãã¥ã¼ã®å¤æ´ãçºçãã¾ãã
å䏿æ¸å
(SPA) ã®é·ç§»ã®å ´åãstartViewTransition()
ã«æ¸¡ããã³ã¼ã«ããã¯ãå¼ã³åºãããDOM ã®å¤æ´ãè¡ãã¾ãã
ã³ã¼ã«ããã¯ãæ£å¸¸ã«å®è¡ãããå ´åãViewTransition.updateCallbackDone
ãããã¹ãå±¥è¡ãããDOM ã®æ´æ°ã«å¯¾å¿ã§ãã¾ãã
ææ¸é (MPA) ã®é·ç§»ã®å ´åãç¾å¨ã®ææ¸ã¨é·ç§»å ã®ææ¸éã§ç§»åãã¾ãã
API ã¯ãæ°ãããã¥ã¼ã®ã¹ãããã·ã§ãããã©ã¤ã表示ã¨ãã¦ãã£ããã£ãã¾ãã
ãã®æç¹ã§ããã¥ã¼ã®é·ç§»ãå®è¡ããããã¨ãã¦ãããViewTransition.ready
ãããã¹ãå±¥è¡ããããããä¾ãã°æ¢å®ã§ã¯ãªãç¬èªã® JavaScript ã¢ãã¡ã¼ã·ã§ã³ãå®è¡ãããªã©ãã¦å¿çãããã¨ãã§ãã¾ãã
å¤ããã¼ã¸ã®ã¹ãããã·ã§ãã㯠"out" ã¢ãã¡ã¼ã·ã§ã³ã§ãæ°ãããã¥ã¼ã®ã¹ãããã·ã§ãã㯠"in" ã¢ãã¡ã¼ã·ã§ã³ã§è¡¨ç¤ºããã¾ããæ¢å®ã§ã¯ãå¤ããã¥ã¼ã®ã¹ãããã·ã§ãã㯠opacity
ã 1 ãã 0 ã«ãæ°ãããã¥ã¼ã®ã¹ãããã·ã§ãã㯠opacity
ã 0 ãã 1 ã«ã¢ãã¡ã¼ã·ã§ã³ã§å¤åãã¦ãã¯ãã¹ãã§ã¼ã广ã«ãªãã¾ãã
é·ç§»ã¢ãã¡ã¼ã·ã§ã³ãçµããã«éããã¨ãViewTransition.finished
ãããã¹ãå±¥è¡ãããå¿çãããã¨ãã§ãã¾ãã
ã¡ã¢: ææ¸å
ã®ãã¼ã¸ã®å¯è¦ç¶æ
ã hidden
ã®å ´åï¼ä¾ãã°ãææ¸ãã¦ã£ã³ãã¦ã®ä¸ã«è¦ããã¦ãããããã©ã¦ã¶ã¼ãæå°åããã¦ããããä»ã®ãã©ã¦ã¶ã¼ã¿ããã¢ã¯ãã£ãã«ãªã£ã¦ããå ´åãªã©ï¼ãdocument.startViewTransition()
ãå¼ã³åºããéã«ããã¥ã¼é·ç§»ã¯å®å
¨ã«ã¹ãããããã¾ãã
æµåºããã³æµå ¥ã®é·ç§»ã¢ãã¡ã¼ã·ã§ã³ã使ããå¦çãè¡ãããã«ãAPI ã¯ä»¥ä¸ã®æ§é ã§æ¬ä¼¼è¦ç´ ããªã¼ãæ§ç¯ãã¾ãã
::view-transition ââ ::view-transition-group(root) ââ ::view-transition-image-pair(root) ââ ::view-transition-old(root) ââ ::view-transition-new(root)
ã¡ã¢: ::view-transition-group
ã®ãµãããªã¼ã¯ããã£ããã£ãããããããã® view-transition-name
ãã¨ã«ä½æããã¾ãã
å䏿æ¸å (SPA) ã®é·ç§»ã®å ´åãæ¬ä¼¼è¦ç´ ããªã¼ã¯ææ¸å ã§å©ç¨ã§ãã¾ããç°ãªãææ¸é (MPA) ã®é·ç§»ã®å ´åãæ¬ä¼¼è¦ç´ ããªã¼ã¯åºåå ææ¸ã§ã®ã¿å©ç¨ã§ãã¾ãã
ããªã¼æ§é ã®æãç¹å¾´çãªé¨åã¯ä»¥ä¸ã®éãã§ãã
::view-transition
ã¯ãã¥ã¼é·ç§»ãªã¼ãã¼ã¬ã¤ã®ã«ã¼ãã§ããããã¹ã¦ã®ãã¥ã¼é·ç§»ã®ã¹ãããã·ã§ããã°ã«ã¼ããæ ¼ç´ããä»ã®ãã¹ã¦ã®ãã¼ã¸ã³ã³ãã³ãã®ä¸ã«ä½ç½®ãã¾ãã
::view-transition-group
ã¯ãåãã¥ã¼é·ç§»ã®ã¹ãããã·ã§ããã°ã«ã¼ãã®ã³ã³ããã¼ã¨ãã¦æ©è½ãã¾ãã弿° root
ã¯æ¢å®ã®ã¹ãããã·ã§ããã°ã«ã¼ããæå®ãããã¥ã¼é·ç§»ã¢ãã¡ã¼ã·ã§ã³ã¯ view-transition-name
ã root
ã§ããã¹ãããã·ã§ããã«é©ç¨ããã¾ãã æ¢å®ã§ã¯ããã㯠:root
è¦ç´ ã§ããããã¯ãæ¢å®ã®ãã©ã¦ã¶ã¼ã®ã¹ã¿ã¤ã«è¨å®ããããå®ç¾©ãã¦ããããã§ãã
:root {
view-transition-name: root;
}
ãã ãããã¼ã¸ã®ä½æè
ã¯ãä¸è¨ã®è¨å®ãè§£é¤ããå¥ã®è¦ç´ ã« view-transition-name: root
ãè¨å®ãããã¨ã§ãããã夿´ã§ãããã¨ã«æ³¨æãã¦ãã ããã
::view-transition-old
ã¯å¤ããã¼ã¸è¦ç´ ã®éçãªã¹ãããã·ã§ããã対象ã¨ãã::view-transition-new
ã¯æ°ãããã¼ã¸è¦ç´ ã®åçãªã¹ãããã·ã§ããã対象ã¨ãã¾ããã©ã¡ããã<img>
ã <video>
ã¨åæ§ã«ç½®æã³ã³ãã³ãã¨ãã¦ã¬ã³ããªã³ã°ããããããobject-fit
ã object-position
ãªã©ã®ä¾¿å©ãªããããã£ã§ã¹ã¿ã¤ã«è¨å®ã§ããã¨ãããã¨ã§ãã
ã¡ã¢: ç°ãªãã«ã¹ã¿ã ãã¥ã¼é·ç§»ã¢ãã¡ã¼ã·ã§ã³ãç°ãªã DOM è¦ç´ ã«é©ç¨ãããã¨ã¯å¯è½ã§ããåè¦ç´ ã«ç°ãªã view-transition-name
ãè¨å®ãããã¨ã§ãç°ãªãã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ã§ãã¾ãããã®ãããªå ´åãåè¦ç´ ã«å¯¾ã㦠::view-transition-group
ã使ããã¾ããä¾ãã°ãç°ãªãè¦ç´ ã«ç°ãªãã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ããæ¹æ³ã«ã¤ãã¦ã¯ããã¾ãã¾ãªè¦ç´ ã«å¯¾ããæ§ã
ãªã¢ãã¡ã¼ã·ã§ã³ãåç
§ãã¦ãã ããã
ã¡ã¢: å¾ã»ã©èª¬æãã¾ãããæµåºã¨æµå
¥ã®ã¢ãã¡ã¼ã·ã§ã³ãã«ã¹ã¿ãã¤ãºããã«ã¯ããããã ::view-transition-old
ããã³ ::view-transition-new
æ¬ä¼¼è¦ç´ ãã¢ãã¡ã¼ã·ã§ã³ã®å¯¾è±¡ã¨ããå¿
è¦ãããã¾ãã
ãã®ç« ã§ã¯ãSPA 㨠MPA ã®ã©ã¡ãã®å ´åã§ããåºæ¬çãªãã¥ã¼é·ç§»ã使ããæ¹æ³ã示ãã¾ãã
åºæ¬ç㪠SPA ãã¥ã¼é·ç§»ä¾ãã°ãSPA ã«ã¯ãæ°ããã³ã³ãã³ããåå¾ããããã²ã¼ã·ã§ã³ãªã³ã¯ãã¯ãªãã¯ããããããµã¼ãã¼ããæ´æ°ãããã·ã¥ããããã¨ãã£ãä½ããã®ã¤ãã³ãã«å¿çã㦠DOM ãæ´æ°ããæ©è½ãªã©ãçãè¾¼ããã¨ãã§ãã¾ããSPA ã®ãã¥ã¼é·ç§»ã®ãã¢ã§ã¯ããã®å¦çããã¯ãªãã¯ããããµã ãã¤ã«ã«åºã¥ãã¦æ°ãããã«ãµã¤ãºã®ç»åã表示ããã displayNewImage()
颿°ã«åç´åãã¦ãã¾ãã ã¾ãããã®å¦çã updateView()
颿°å
ã«ã«ãã»ã«åãããã©ã¦ã¶ã¼ã対å¿ãã¦ããå ´åã«ã®ã¿ãã¥ã¼é·ç§» API ãå¼ã³åºãããã«ãã¦ãã¾ãã
function updateView(event) {
// ã¤ãã³ããçºè¡ãããã®ã <a> 㨠<img> ã®ã©ã¡ããªã®ãã®éããå¦ç
const targetIdentifier = event.target.firstChild || event.target;
const displayNewImage = () => {
const mainSrc = `${targetIdentifier.src.split("_th.jpg")[0]}.jpg`;
galleryImg.src = mainSrc;
galleryCaption.textContent = targetIdentifier.alt;
};
// ãã¥ã¼é·ç§»ã«æªå¯¾å¿ã®ãã©ã¦ã¶ã¼ç¨ã®ä»£æ¿å¦ç
if (!document.startViewTransition) {
displayNewImage();
return;
}
// ãã¥ã¼é·ç§»ã®å ´å
const transition = document.startViewTransition(() => displayNewImage());
}
ãã®ã³ã¼ãã§ã表示ããã¦ããç»åéã®é·ç§»ãååã«å¦çã§ãã¾ãã対å¿ãã¦ãããã©ã¦ã¶ã¼ã§ã¯ãå¤ãç»åããæ°ããç»åããã£ãã·ã§ã³ã¸ã®å¤æ´ãã¹ã ã¼ãºãªã¯ãã¹ãã§ã¼ã(æ¢å®ã®è¡¨ç¤ºé·ç§»)ã§è¡¨ç¤ºããã¾ããããã¯ã対å¿ãã¦ããªããã©ã¦ã¶ã¼ã§ãåä½ãã¾ãããç´ æµãªã¢ãã¡ã¼ã·ã§ã³ã¯è¡¨ç¤ºããã¾ããã
åºæ¬ç㪠MPA ãã¥ã¼é·ç§»ææ¸é (MPA) ã®ãã¥ã¼é·ç§»ã使ããéã«ã¯ãSPA ã®å ´åãããããã«å¦çãç°¡åã«ãªãã¾ããJavaScript ã¯å¿
è¦ããã¾ããããã¥ã¼ã®æ´æ°ã¯ãJavaScript ã«ãã DOM ã®å¤æ´ã§ã¯ãªããææ¸éãåä¸ãªãªã¸ã³å
ã®ç§»åã«ãã£ã¦çºçããããã§ããåºæ¬ç㪠MPA ãã¥ã¼é·ç§»ãæå¹ã«ããã«ã¯ãç¾å¨ã®ææ¸ã¨åºåå
ã®ææ¸ã®ã©ã¡ãããªããã¤ã³ããããã«ãCSS ã§ @view-transition
ã¢ããã«ã¼ã«ãæå®ããå¿
è¦ãããã¾ãã
@view-transition {
navigation: auto;
}
å½ç¤¾ã® MPA ã®ãã¥ã¼é·ç§»ã®ãã¢ã§ã¯ããã®ã¢ããã«ã¼ã«ãå®éã«è¡¨ç¤ºãããããã«ããã¥ã¼é·ç§»ã®æµåºããã³æµå ¥ã®ã¢ãã¡ã¼ã·ã§ã³ãã«ã¹ã¿ãã¤ãºããæ¹æ³ã示ãã¦ãã¾ãã
ã¡ã¢: ç¾å¨ãMPA ã®ãã¥ã¼é·ç§»ã¯åä¸ãªãªã¸ã³ææ¸éã§ãã使ã§ãã¾ããããå°æ¥çãªå®è£ ã§ã¯ãã®å¶éãç·©åãããå¯è½æ§ãããã¾ãã
ã¢ãã¡ã¼ã·ã§ã³ã®ã«ã¹ã¿ãã¤ãºãã¥ã¼é·ç§»ã®æ¬ä¼¼è¦ç´ ã¯ãæ¢å®ã§ CSS ã¢ãã¡ã¼ã·ã§ã³ãè¨å®ããã¦ãã¾ããï¼è©³ç´°ã¯ãªãã¡ã¬ã³ã¹ãã¼ã¸ãåç §ï¼ã
ã»ã¨ãã©ã®å¤è¦³ã®é·ç§»ã«ã¯ãåè¿°ã®ã¨ãããæ¢å®ã§ã¹ã ã¼ãºãªã¯ãã¹ãã§ã¼ãã®ã¢ãã¡ã¼ã·ã§ã³ãæå®ããã¦ãã¾ãããã ããä¾å¤ãããã¾ãã
height
㨠width
ã®é·ç§»ã«ã¯ãã¹ã ã¼ãºãªæ¡å¤§ç¸®å°ã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ããã¾ããposition
㨠transform
ã®é·ç§»ã«ã¯ãã¹ã ã¼ãºãªåãã®ã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ããã¾ããæ¢å®ã®ã¢ãã¡ã¼ã·ã§ã³ã¯ãé常㮠CSS ã使ç¨ãã¦å¥½ããªããã«å¤æ´ãããã¨ãã§ãã¾ãã"from" ã¢ãã¡ã¼ã·ã§ã³ã対象ã¨ããã«ã¯ ::view-transition-old
ãã"to" ã¢ãã¡ã¼ã·ã§ã³ã対象ã¨ããã«ã¯ ::view-transition-new
ã使ç¨ãã¾ãã
ä¾ãã°ã両æ¹ã®é度ã夿´ããã«ã¯ã次ã®ããã«ãã¾ãã
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.5s;
}
::view-transition-group()
ã対象ã¨ã㦠::view-transition-old()
㨠::view-transition-new()
ã«ã¹ã¿ã¤ã«ãé©ç¨ãããã¨ããå§ããã¾ããæ¬ä¼¼è¦ç´ ã®éå±¤ã¨æ¢å®ã®ã¦ã¼ã¶ã¼ã¨ã¼ã¸ã§ã³ãã¹ã¿ã¤ã«è¨å®ã«ãããã©ã¡ããã¹ã¿ã¤ã«ãç¶æ¿ããã¾ããä¾ãã°æ¬¡ã®ããã«ãã¾ãã
::view-transition-group(root) {
animation-duration: 0.5s;
}
ã¡ã¢: ããã¯ãã³ã¼ããä¿è·ããã®ã«ãè¯ããªãã·ã§ã³ã§ãã::view-transition-group()
ãã¢ãã¡ã¼ã·ã§ã³ããã®ã§ã group
/image-pair
æ¬ä¼¼è¦ç´ 㨠old
ããã³ new
æ¬ä¼¼è¦ç´ ã§åçæéãç°ãªãã¨ããçµæã«ãªãå¯è½æ§ãããã¾ãã
ææ¸é (MPA) é·ç§»ã®å ´åããã¥ã¼é·ç§»ãæ©è½ããã«ã¯ãæ¬ä¼¼è¦ç´ ãåºåå ææ¸ã«ãè¨è¼ããå¿ è¦ãããã¾ããåæ¹åã§ãã¥ã¼é·ç§»ã使ç¨ãããå ´åã¯ããã¡ããã©ã¡ãã«ãè¨è¼ããå¿ è¦ãããã¾ãã
ç§ãã¡ã® MPA ã®ãã¥ã¼é·ç§»ã®ãã¢ã§ã¯ãä¸è¨ã® CSS ãå«ãã§ãã¾ãããã«ã¹ã¿ãã¤ãºãããã«ä¸æ©é²ããã«ã¹ã¿ã ã¢ãã¡ã¼ã·ã§ã³ãå®ç¾©ããããã ::view-transition-old(root)
ããã³ ::view-transition-new(root)
æ¬ä¼¼è¦ç´ ã«é©ç¨ãã¦ãã¾ãããã®çµæãããã²ã¼ã·ã§ã³ãçºçããã¨ãæ¢å®ã®ã¯ãã¹ãã§ã¼ãé·ç§»ããã¹ã¯ã¤ãã¢ãããé·ç§»ã«ç½®ãæããã¾ãã
/* ç¬èªã¢ãã¡ã¼ã·ã§ã³ã®ä½æ */
@keyframes move-out {
from {
transform: translateY(0%);
}
to {
transform: translateY(-100%);
}
}
@keyframes move-in {
from {
transform: translateY(100%);
}
to {
transform: translateY(0%);
}
}
/* æ°æ§ã®ãã¼ã¸ã®ç¶æ
ã«ã«ã¹ã¿ã ã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ */
::view-transition-old(root) {
animation: 0.4s ease-in both move-out;
}
::view-transition-new(root) {
animation: 0.4s ease-in both move-in;
}
ãã¾ãã¾ãªè¦ç´ ã«å¯¾ããæ§ã
ãªã¢ãã¡ã¼ã·ã§ã³
æ¢å®ã§ã¯ããã¥ã¼ã®æ´æ°ä¸ã«å¤æ´ãããããããã®è¦ç´ ã¯ãã¹ã¦ãåãã¢ãã¡ã¼ã·ã§ã³ã使ç¨ãã¦é·ç§»ãã¾ãã æ¢å®ã® root
ã¢ãã¡ã¼ã·ã§ã³ã¨ã¯ç°ãªãã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ãããè¦ç´ ãããå ´åã¯ãview-transition-name
ããããã£ã使ç¨ãã¦ããããåé¢ãããã¨ãã§ãã¾ãã ä¾ãã°ãSPA ã®ãã¥ã¼é·ç§»ã®ãã¢ã§ã¯ã<figcaption>
è¦ç´ ã« view-transition-name
ã¨ã㦠figure-caption
ãæå®ããããã¥ã¼é·ç§»ã®è¦³ç¹ãããã¼ã¸ã®ä»ã®é¨åã¨åºå¥ããã¦ãã¾ãã
figcaption {
view-transition-name: figure-caption;
}
ãã® CSS ãé©ç¨ããã¨ãçæãããæ¬ä¼¼è¦ç´ ããªã¼ã¯ãã®ããã«ãªãã¾ãã
::view-transition ââ ::view-transition-group(root) â ââ ::view-transition-image-pair(root) â ââ ::view-transition-old(root) â ââ ::view-transition-new(root) ââ ::view-transition-group(figure-caption) ââ ::view-transition-image-pair(figure-caption) ââ ::view-transition-old(figure-caption) ââ ::view-transition-new(figure-caption)
2 ã¤ç®ã®çä¼¼è¦ç´ ãè¨å®ãããã¨ã§ã<figcaption>
ã ãã«å¥åã®ãã¥ã¼é·ç§»ã¹ã¿ã¤ã«è¨å®ãé©ç¨ãããã¨ãã§ãã¾ãã ç°ãªãå¤ããã¥ã¼ã¨æ°ãããã¥ã¼ã¯ãããããå¥åã«å¦çããã¾ãã
ã¡ã¢: view-transition-name
ã®å¤ã¯ãnone
ãé¤ãã¦ä½ããã®å¤ã«ãããã¨ãã§ãã¾ããnone
ã®å¤ã¯ãç¹å®ã®è¦ç´ ããã¥ã¼é·ç§»ã«åå ããªãã¨ãããã¨ãæå³ãã¦ãã¾ãã
view-transition-name
ã®å¤ãåºæã®ãã®ã§ãªããã°ãªãã¾ããã ã¬ã³ããªã³ã°ãããè¦ç´ ãåæã«åã view-transition-name
ãä¿æãã¦ããå ´åãViewTransition.ready
ãæå¦ãããé·ç§»ãã¹ãããããã¾ãã
以ä¸ã®ã³ã¼ã㯠<figcaption>
ã ãã«ç¬èªã®ã¢ãã¡ã¼ã·ã§ã³ãé©ç¨ãã¾ãã
@keyframes grow-x {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
@keyframes shrink-x {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
::view-transition-group(figure-caption) {
height: auto;
right: 0;
left: auto;
transform-origin: right center;
}
::view-transition-old(figure-caption) {
animation: 0.25s linear both shrink-x;
}
::view-transition-new(figure-caption) {
animation: 0.25s 0.25s linear both grow-x;
}
ããã§ã¯ãç¬èªã® CSS ã¢ãã¡ã¼ã·ã§ã³ã使ããããã ::view-transition-old(figure-caption)
ããã³ ::view-transition-new(figure-caption)
æ¬ä¼¼è¦ç´ ã«é©ç¨ãã¦ãã¾ãã ã¾ããã©ã¡ããåãä½ç½®ã«ç¶æããæ¢å®ã®ã¹ã¿ã¤ã«ãç¬èªã®ã¢ãã¡ã¼ã·ã§ã³ã«å¹²æ¸ããªãããã«ãä»ã«ãããã¤ãã®ã¹ã¿ã¤ã«ã追å ãã¦ãã¾ãã
ã¡ã¢: æ¬ä¼¼è¦ç´ ã®èå¥åã¨ã㦠*
ã使ç¨ããã¨ãååã«é¢ä¿ãªãããã¹ã¦ã®ã¹ãããã·ã§ããæ¬ä¼¼è¦ç´ ã対象ã¨ãããã¨ãã§ãã¾ããä¾ãã°ã次ã®ããã«ãã¾ãã
::view-transition-group(*) {
animation-duration: 2s;
}
æ¢å®ã®ã¢ãã¡ã¼ã·ã§ã³ã¹ã¿ã¤ã«ã®å©ç¹
ãªããããã·ã³ãã«ã§ãããè¯ãçµæãããããå¥ã®é·ç§»ãªãã·ã§ã³ãçºè¦ãã¾ãããæçµç㪠<figcaption>
ãã¥ã¼é·ç§»ã¯ã以ä¸ã®ãããªå½¢ã«ãªãã¾ããã
figcaption {
view-transition-name: figure-caption;
}
::view-transition-group(figure-caption) {
height: 100%;
}
ããã¯ãã¾ãåä½ãã¾ããæ¢å®ã§ã¯ã::view-transition-group
ããå¤ããã¥ã¼ã¨æ°ãããã¥ã¼ã®éã§ã¹ã ã¼ãºã«å¤åããªãããwidth
㨠height
ãç§»è¡ãããããã§ããã©ã¡ãã®ç¶æ
ã§ã height
ãåºå®ãã¦è¨å®ããã ãã§ããã¾ãããããã«ãªãã¾ããã
ã¡ã¢: Smooth and simple transitions with the View Transitions API ã«ã¯ãä»ã«ãããã¤ãã®ã«ã¹ã¿ãã¤ãºä¾ãããã¾ãã
JavaScript ã«ãããã¥ã¼é·ç§»ã®å¶å¾¡ãã¥ã¼é·ç§»ã«ã¯ãViewTransition
ãªãã¸ã§ã¯ãã®ã¤ã³ã¹ã¿ã³ã¹ãé¢é£ä»ãããã¦ããããã®ãªãã¸ã§ã¯ãã«ã¯ãé·ç§»ã®ãã¾ãã¾ãªç¶æ
ã«å°éããéã« JavaScript ãå®è¡ã§ããããã«ãããããã¹ã¡ã³ãã¼ãããã¤ãããã¾ããä¾ãã°ãViewTransition.ready
ã¯ãæ¬ä¼¼è¦ç´ ããªã¼ã使ãããã¢ãã¡ã¼ã·ã§ã³ãéå§ãããã¨å±¥è¡ããã ViewTransition.finished
ã¯ãã¢ãã¡ã¼ã·ã§ã³ãçµäºããæ°ãããã¼ã¸ãã¥ã¼ãã¦ã¼ã¶ã¼ã«å¯¾ãã¦è¡¨ç¤ºãããæä½å¯è½ã«ãªãã¨å±¥è¡ããã¾ãã
ViewTransition
ã«ã¯æ¬¡ã®ããã«ã¢ã¯ã»ã¹ã§ãã¾ãã
document.startViewTransition()
ã¡ã½ãããé·ç§»ã«é¢é£ä»ãããã ViewTransition
ãè¿ãã¾ããpageswap
ã¤ãã³ããçºè¡ããã¾ããã¤ãã³ããªãã¸ã§ã¯ã (PageSwapEvent
) ã¯ãViewTransition
ã«PageSwapEvent.viewTransition
ããããã£ããã¢ã¯ã»ã¹ã§ããã»ããããã²ã¼ã·ã§ã³ã®ç¨®é¡ã¨ç¾å¨ã®ææ¸ããã³ç§»åå
ææ¸ã®å±¥æ´é
ç®ãå«ã NavigationActivation
ã«ã PageSwapEvent.activation
ããã¢ã¯ã»ã¹ã§ãã¾ãã
ã¡ã¢: ããã²ã¼ã·ã§ã³ã®ãªãã¤ã¬ã¯ããã§ã¼ã³ã®ã©ããã«ãªãªã¸ã³ãã¾ããã URL ãããå ´åãactivation
ããããã£ã¯ null
ãè¿ãã¾ãã
pagereveal
ã¤ãã³ããçºçãã¾ããããã¯ããããã¯ã¼ã¯ããæ°ããææ¸ãèªã¿è¾¼ãã å ´åãã¾ãã¯ï¼ããã¯/ãã©ã¯ã¼ããã£ãã·ã¥ (bfcache) ã¾ãã¯äºåã¬ã³ããªã³ã°ï¼ææ¸ãã¢ã¯ãã£ãã«ããå ´åã§ããã¤ãã³ããªãã¸ã§ã¯ã (PageRevealEvent
) ã¯ãViewTransition
ã« PageRevealEvent.viewTransition
ããããã£ãä»ãã¦ã¢ã¯ã»ã¹ã§ãã¾ãããããã®æ©è½ãã©ã®ããã«ä½¿ç¨ã§ãããã示ãããã«ãããã¤ãã®ã³ã¼ãä¾ãè¦ã¦ããã¾ãããã
JavaScript ãæ´»ç¨ããç¬èªã®ææ¸å (SPA) é·ç§»ä»¥ä¸ã® JavaScript ã使ç¨ãããã¨ã§ãã¯ãªãã¯æã«ã¦ã¼ã¶ã¼ã®ã«ã¼ã½ã«ä½ç½®ããåå½¢ã®ããªãã¼ã«ããã¥ã¼é·ç§»ã使ãããã¨ãã§ãã¾ããã¦ã§ãã¢ãã¡ã¼ã·ã§ã³ API ã§æå®ãããã¢ãã¡ã¼ã·ã§ã³ãæä¾ããã¾ãã
// æå¾ã®ã¯ãªãã¯ã¤ãã³ããæ ¼ç´
let lastClick;
addEventListener("click", (event) => (lastClick = event));
function spaNavigate(data) {
// ãã® API ã«å¯¾å¿ãã¦ããªããã©ã¦ã¶ã¼ç¨ã®ä»£æ¿å¦ç
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
// ã¯ãªãã¯ä½ç½®ãåå¾ãã失ææã¯ç»é¢ã®ä¸å¤®ã«ãã
const x = lastClick?.clientX ?? innerWidth / 2;
const y = lastClick?.clientY ?? innerHeight / 2;
// æãé ãè§ã¾ã§ã®è·é¢ãåå¾
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
);
// é·ç§»ã使
const transition = document.startViewTransition(() => {
updateTheDOMSomehow(data);
});
// æ¬ä¼¼è¦ç´ ã使ãããã¾ã§å¾
ã¤
transition.ready.then(() => {
// ã«ã¼ãè¦ç´ ã®æ°ãããã¥ã¼ãã¢ãã¡ã¼ã·ã§ã³
document.documentElement.animate(
{
clipPath: [
`circle(0 at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration: 500,
easing: "ease-in",
// Specify which pseudo-element to animate
pseudoElement: "::view-transition-new(root)",
},
);
});
}
ãã®ã¢ãã¡ã¼ã·ã§ã³ã§ã¯ã以ä¸ã® CSS ãå¿ è¦ã¨ãªãã¾ããããã¯ãæ¢å®ã® CSS ã¢ãã¡ã¼ã·ã§ã³ãç¡å¹ã«ããæ°æ§ã®ãã¥ã¼ã®ç¶æ ãæ··ããåãã®ãé²ãããã§ãï¼é·ç§»ã§ã¯ãªãæ°ããç¶æ ãå¤ãç¶æ ã®ä¸ã«ãã¯ã¤ãããããããã«ãªãã¾ãï¼ã
::view-transition-image-pair(root) {
isolation: auto;
}
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
display: block;
}
JavaScript ãæ´»ç¨ããç¬èªã®ææ¸é (MPA) é·ç§»
List of Chrome DevRel team members ã®ãã¢ã§ã¯ããã¼ã ã®ãããã£ã¼ã«ãã¼ã¸ã®åºæ¬è¨å®ãæä¾ããpageswap
ããã³ pagereveal
ã¤ãã³ãã使ç¨ãã¦ã"from" 㨠"to" ã® URL ã«åºã¥ãã¦ãææ¸éãã¥ã¼é·ç§»ã«ãããæµåºã»æµå
¥ã¢ãã¡ã¼ã·ã§ã³ãã«ã¹ã¿ãã¤ãºããæ¹æ³ã説æãã¦ãã¾ãã
pageswap
ã¤ãã³ãã®ãªã¹ãã¼ã¯æ¬¡ã®ããã«ãªãã¾ããããã«ããããããã£ã¼ã«ãã¼ã¸ã«ãªã³ã¯ãããæµåºãã¼ã¸ä¸ã®è¦ç´ ã«ãã¥ã¼é·ç§»ã®ååãè¨å®ããã¾ãããã¼ã ãã¼ã¸ãããããã£ã¼ã«ãã¼ã¸ã«ç§»åããéãã¯ãªãã¯ããããªã³ã¯è¦ç´ ã«å¯¾ãã¦ã®ã¿ãç¬èªã®ã¢ãã¡ã¼ã·ã§ã³ãæå®ããã¾ãã
window.addEventListener("pageswap", async (e) => {
// ã¢ã¯ãã£ããªãã¥ã¼é·ç§»ãåå¨ããå ´åã®ã¿å®è¡
if (e.viewTransition) {
const currentUrl = e.activation.from?.url
? new URL(e.activation.from.url)
: null;
const targetUrl = new URL(e.activation.entry.url);
// ãããã£ã¼ã«ãã¼ã¸ãããã¼ã ãã¼ã¸ã¸ç§»å
// ~> 大ããªç»åã¨ã¿ã¤ãã«ã䏿ä¸åº¦ã«è¡¨ç¤ºããã
if (isProfilePage(currentUrl) && isHomePage(targetUrl)) {
// ã¢ãã¡ã¼ã·ã§ã³ãããè¦ç´ ã« view-transition-name ã®å¤ãè¨å®
document.querySelector(`#detail main h1`).style.viewTransitionName =
"name";
document.querySelector(`#detail main img`).style.viewTransitionName =
"avatar";
// ã¹ãããã·ã§ãããæ®å½±ãããå¾ããã¥ã¼é·ç§»åãé¤å»ãã
// BFCache ã«ãã¼ã¸ã®ç¶æ
ãç¶æããããã¨ã«ããååã®ç«¶åã鲿¢ãã
await e.viewTransition.finished;
document.querySelector(`#detail main h1`).style.viewTransitionName =
"none";
document.querySelector(`#detail main img`).style.viewTransitionName =
"none";
}
// Going to profile page
// ~> The clicked items are the ones!
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// ã¢ãã¡ã¼ã·ã§ã³ãããè¦ç´ ã« view-transition-name ã®å¤ãè¨å®
document.querySelector(`#${profile} span`).style.viewTransitionName =
"name";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"avatar";
// ã¹ãããã·ã§ãããæ®å½±ãããå¾ããã¥ã¼é·ç§»åãé¤å»ãã
// BFCache ã«ãã¼ã¸ã®ç¶æ
ãç¶æããããã¨ã«ããååã®ç«¶åã鲿¢ãã
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName =
"none";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"none";
}
}
});
ã¡ã¢: view-transition-name
ã®å¤ã¯ãããããã®å ´åã§ã¹ãããã·ã§ãããåå¾ãããå¾ã«é¤å»ãã¾ãã è¨å®ããã¾ã¾ã«ãã¦ããã¨ãããã²ã¼ã·ã§ã³ã®éã« bfcache ã«ä¿åããããã¼ã¸ã®ç¶æ
ã«ä¿åããã¦ãã¾ãã¾ãã ãã®å¾ãæ»ããã¿ã³ãæ¼ãããã¨ãããã²ã¼ã·ã§ã³åã®ãã¼ã¸ã® pagereveal
ã¤ãã³ããã³ãã©ã¼ããç°ãªãè¦ç´ ã«å¯¾ãã¦åã view-transition-name
ã®å¤ãè¨å®ãããã¨è©¦ã¿ã¾ãã è¤æ°ã®è¦ç´ ã«åã view-transition-name
è¨å®ããã¦ããå ´åããã¥ã¼é·ç§»ã¯ã¹ãããããã¾ãã
pagereveal
ã¤ãã³ãã®ãªã¹ãã¼ã¯ã以ä¸ã®ããã«ãã¾ããããã¯ãpageswap
ã¤ãã³ããªã¹ãã¼ã¨ä¼¼ãæ¹æ³ã§åä½ãã¾ãããæ°ãããã¼ã¸ã®ãã¼ã¸è¦ç´ ã«å¯¾ã㦠"to" ã¢ãã¡ã¼ã·ã§ã³ãã«ã¹ã¿ãã¤ãºãã¦ãããã¨ã«çæãã¦ãã ããã
window.addEventListener("pagereveal", async (e) => {
// "from" å±¥æ´é
ç®ãåå¨ããªãå ´åã¯ãæ»ã
if (!navigation.activation.from) return;
// ã¢ã¯ãã£ããªãã¥ã¼é·ç§»ãåå¨ããå ´åã®ã¿å®è¡
if (e.viewTransition) {
const fromUrl = new URL(navigation.activation.from.url);
const currentUrl = new URL(navigation.activation.entry.url);
// ãããã£ã¼ã«ãã¼ã¸ãããã¼ã ãã¼ã¸ã«ç§»å
// ~> VT åãé¢é£ãããªã¹ãã¢ã¤ãã ã«è¨å®
if (isProfilePage(fromUrl) && isHomePage(currentUrl)) {
const profile = extractProfileNameFromUrl(fromUrl);
// ã¢ãã¡ã¼ã·ã§ã³ãããè¦ç´ ã« view-transition-name ã®å¤ãè¨å®
document.querySelector(`#${profile} span`).style.viewTransitionName =
"name";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"avatar";
// ã¹ãããã·ã§ãããæ®å½±ãããå¾ã«ååãé¤å»ãã
// ãã®ãããæ¬¡ã®ããã²ã¼ã·ã§ã³ã«åãããã¨ãã§ãã
await e.viewTransition.ready;
document.querySelector(`#${profile} span`).style.viewTransitionName =
"none";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"none";
}
// ãããã£ã¼ã«ãã¼ã¸ã¸ç§»åãã
// ~> ã¡ã¤ã³ã¿ã¤ãã«ã¨ç»åã« VT åã追å
if (isProfilePage(currentUrl)) {
// ã¢ãã¡ã¼ã·ã§ã³ãããè¦ç´ ã« view-transition-name ã®å¤ãè¨å®
document.querySelector(`#detail main h1`).style.viewTransitionName =
"name";
document.querySelector(`#detail main img`).style.viewTransitionName =
"avatar";
// ã¹ãããã·ã§ãããæ®å½±ãããå¾ã«ååãé¤å»ãã
// ãã®ãããæ¬¡ã®ããã²ã¼ã·ã§ã³ã«åãããã¨ãã§ãã
await e.viewTransition.ready;
document.querySelector(`#detail main h1`).style.viewTransitionName =
"none";
document.querySelector(`#detail main img`).style.viewTransitionName =
"none";
}
}
});
ãã¼ã¸ã®ç¶æ
ãå®å®åãããææ¸éã®é·ç§»ãä¸è²«æ§ã®ãããã®ã«ãã
ææ¸éã®é·ç§»ãå®è¡ããåã«ãã¬ã³ãã¼ãããã¯ãå©ç¨ãã¦ãã¼ã¸ã®ç¶æ ãå®å®ããã¾ã§å¾ ã¤ã®ãçæ³çã§ãã
ã¹ã¿ã¤ã«ã¯æ¢å®ã§ã¯ã¬ã³ãã¼ãããã¯ãããã¹ã¯ãªãã㯠blocking="render"
屿§ã使ç¨ãã¦ã¬ã³ãã¼ãããã¯ãããã¨ãã§ãã¾ãã
é·ç§»ã¢ãã¡ã¼ã·ã§ã³ãå®è¡ãããåã«ãåæã® HTML ã確å®ã«è§£æããã常ã«ä¸è²«ããã¬ã³ããªã³ã°ãè¡ããããã¨ãä¿è¨¼ããã«ã¯ã<link rel="expect">
ã使ç¨ãããã¨ãã§ãã¾ãããã®è¦ç´ ã«ã¯ã以ä¸ã®å±æ§ãå«ãããã¨ãã§ãã¾ãã
rel="expect"
ã¯ããã® <link>
è¦ç´ ã使ç¨ãã¦ããã¼ã¸ä¸ã® HTML ãã¬ã³ãã¼ãããã¯ãããã¨ã示ãã¾ããhref="#element-id"
ã¯ãã¬ã³ãã¼ãããã¯ãããè¦ç´ ã® ID ã示ãã¾ããblocking="render"
ã¯ãæå®ããã HTML ã®ã¬ã³ãã¼ãããã¯ããã¾ãããã®ä¾ãåç´ãªä¾ã® HTML ææ¸ã§è¦ã¦ããã¾ãããã
<!doctype html>
<html lang="ja">
<head>
<!-- ããã¯æ¢å®ã§ã¬ã³ãã¼ãããã¯ããã -->
<link rel="stylesheet" href="style.css" />
<!-- éè¦ãªã¹ã¯ãªãããã¬ã³ãã¼ãããã¯ã¨ãã¦ãã¼ã¯ããã¨ã
ãã¥ã¼é·ç§»ãæå¹åãããåã«ç¢ºå®ã«å®è¡ãããããä¿è¨¼ããã -->
<script async href="layout.js" blocking="render"></script>
<!-- rel="expect" ããã³ã blocking="render" ã使ç¨ãã¦ã
"#lead-content" è¦ç´ ã確å®ã«è¡¨ç¤ºãããå®å
¨ã«è§£éã§ããç¶æ
ã«
ããã¾ã¾ãé·ç§»ãèµ·åãã -->
<link rel="expect" href="#lead-content" blocking="render" />
</head>
<body>
<h1>Page title</h1>
<nav>...</nav>
<div id="lead-content">
<section id="first-section">æåã®ç¯</section>
<section>äºçªç®ã®ç¯</section>
</div>
</body>
</html>
ãã®çµæããªã¼ãã³ã³ãã³ãã§ãã <div>
ãè§£éã§ããã¾ã§ãææ¸å
ã®ã¬ã³ããªã³ã°ããããã¯ãããä¸è²«ãããã¥ã¼é·ç§»ãä¿è¨¼ã§ãã¾ãã
ã¾ãã media
屿§ã <link rel="expect">
è¦ç´ ã«æå®ãããã¨ãã§ãã¾ããä¾ãã°ãç»é¢ãçã端æ«ã§ãã¼ã¸ãèªã¿è¾¼ãã éã«ã¯ãåºãç»é¢ã®ç«¯æ«ã§èªã¿è¾¼ãå ´åããããã³ã³ãã³ãã®ã¬ã³ããªã³ã°ããããã¯ãããå ´åãããããããã¾ãããããã¯çã«ããªã£ã¦ãã¾ããã¢ãã¤ã«ç«¯æ«ã§ã¯ããã¹ã¯ãããã®å ´åãããããã¼ã¸ãæåã«èªã¿è¾¼ã¾ããéã«ã¯ã³ã³ãã³ããå°ãªã表示ãããããã§ãã
ããã¯ã次㮠HTML ã§å®ç¾ã§ãã¾ãã
<link
rel="expect"
href="#lead-content"
blocking="render"
media="screen and (min-width: 641px)" />
<link
rel="expect"
href="#first-section"
blocking="render"
media="screen and (max-width: 640px)" />
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4