Add hotpot navigation and slideshow
Signed-off-by: Justin Georgi <justin.georgi@gmail.com>
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
namespace MediaWiki\Extension\GlModelViewer;
|
namespace MediaWiki\Extension\GlModelViewer;
|
||||||
|
|
||||||
use MediaTransformOutput;
|
use MediaTransformOutput;
|
||||||
|
use ConfigFactory;
|
||||||
|
use OutputPage;
|
||||||
use Html;
|
use Html;
|
||||||
|
|
||||||
class GlModelTransformOutput extends MediaTransformOutput {
|
class GlModelTransformOutput extends MediaTransformOutput {
|
||||||
@@ -157,8 +159,40 @@ class GlModelTransformOutput extends MediaTransformOutput {
|
|||||||
$attrMenu = array(
|
$attrMenu = array(
|
||||||
'class' => 'glmv-menu'
|
'class' => 'glmv-menu'
|
||||||
);
|
);
|
||||||
|
$mainConfig = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
|
||||||
|
$menuUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/menu_arrow.svg';
|
||||||
|
$attrMenuImg = array (
|
||||||
|
'class' => 'glmv-menu-image',
|
||||||
|
'src' => $menuUrl
|
||||||
|
);
|
||||||
|
$menuImg = Html::rawElement('img', $attrMenuImg, '');
|
||||||
|
|
||||||
return Html::rawElement('div', $attrMenu, '>');
|
$gotoUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/goto_hs.svg';
|
||||||
|
$attrMenuButtonPrev = array (
|
||||||
|
'class' => 'glmv-menu-button prev-hs',
|
||||||
|
'onclick' => 'prevAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
|
);
|
||||||
|
$attrMenuButtonNext = array (
|
||||||
|
'class' => 'glmv-menu-button next-hs',
|
||||||
|
'onclick' => 'nextAnnotation(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
|
);
|
||||||
|
|
||||||
|
$slideUrl = $mainConfig->get( 'ExtensionAssetsPath' ) . '/GlModelViewer/resources/hs_slideshow.svg';
|
||||||
|
$attrMenuButtonSlides = array (
|
||||||
|
'class' => 'glmv-menu-button',
|
||||||
|
'onclick' => 'event.target.toggleAttribute("toggled"); slideshowAnnotations(event.target.closest(".glmv-container").querySelector("model-viewer"))',
|
||||||
|
'onmousedown' => 'event.stopPropagation()',
|
||||||
|
'ontouchstart' => 'event.stopPropagation()'
|
||||||
|
);
|
||||||
|
$buttonPrev = Html::rawElement('div', $attrMenuButtonPrev, '<img src="' . $gotoUrl . '"></image>');
|
||||||
|
$buttonNext = Html::rawElement('div', $attrMenuButtonNext, '<img src="' . $gotoUrl . '"></image>');
|
||||||
|
$buttonSlides = Html::rawElement('div', $attrMenuButtonSlides, '<img src="' . $slideUrl . '"></image>');
|
||||||
|
|
||||||
|
return Html::rawElement('div', $attrMenu, $menuImg . $buttonPrev . $buttonSlides . $buttonNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -74,14 +74,51 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
transition: width .75s;
|
transition: width .75s;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 50px;
|
bottom: 50px;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
width: 100%
|
width: auto;
|
||||||
|
|
||||||
|
& .glmv-menu-image {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glmv-menu-image {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
position: relative;
|
||||||
|
transition: transform .75s;
|
||||||
|
flex: 0 0 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glmv-menu-button {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
position: relative;
|
||||||
|
margin: 2px;
|
||||||
|
flex: 0 0 28px;
|
||||||
|
|
||||||
|
& img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[toggled] {
|
||||||
|
background: #00000033;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev-hs img {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
let slideShowInterval = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets listener and attributes on model-viewer to
|
* Sets listener and attributes on model-viewer to
|
||||||
* allow for click registering of a new hotspot
|
* allow for click registering of a new hotspot
|
||||||
@@ -151,5 +153,10 @@ prevAnnotation = function(mView) {
|
|||||||
* @return {intervalID} ID of the created interval timer
|
* @return {intervalID} ID of the created interval timer
|
||||||
*/
|
*/
|
||||||
slideshowAnnotations = function(mView, slideDuration = 5000) {
|
slideshowAnnotations = function(mView, slideDuration = 5000) {
|
||||||
return setInterval(nextAnnotation, slideDuration, mView)
|
if (slideShowInterval) {
|
||||||
|
clearInterval(slideShowInterval)
|
||||||
|
} else {
|
||||||
|
nextAnnotation(mView)
|
||||||
|
slideShowInterval = setInterval(nextAnnotation, slideDuration, mView)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
resources/goto_hs.svg
Normal file
1
resources/goto_hs.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="40px" viewBox="0 -960 960 960" width="40px" fill="#5f6368"><path d="M768-364.67q-48.33 0-81.17-33.16Q654-431 654-479.33q0-48.34 32.83-81.5Q719.67-594 768-594q47.67 0 80.83 33.17Q882-527.67 882-479.33q0 48.33-33.17 81.5-33.16 33.16-80.83 33.16ZM361.33-286l-46.66-47.67L425-445.33H77.33v-68H425L314.67-624.67 361.33-672l192 192.67-192 193.33Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 397 B |
1
resources/hs_slideshow.svg
Normal file
1
resources/hs_slideshow.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="40px" viewBox="0 -960 960 960" width="40px" fill="#5f6368"><path d="M113.27-240Q83-240 61.5-261.56 40-283.12 40-313.39q0-30.28 21.5-51.78 21.49-21.5 51.68-21.5 5.49 0 10.32.34 4.83.33 11.83 2.33l194-194q-2-7-2.33-11.83-.33-4.84-.33-10.33 0-30.18 21.56-51.68 21.55-21.49 51.83-21.49 30.27 0 51.77 21.59 21.5 21.59 21.5 51.9 0 1.84-2.66 21.84L578-470.67q7-2 11.83-2.33 4.84-.33 10.17-.33t10.17.33q4.83.33 11.83 2.33l154-154q-2-7-2.33-11.83-.34-4.83-.34-10.32 0-30.19 21.56-51.68 21.56-21.5 51.84-21.5 30.27 0 51.77 21.56 21.5 21.56 21.5 51.83 0 30.28-21.5 51.78-21.49 21.5-51.68 21.5-5.49 0-10.32-.34-4.83-.33-11.83-2.33l-154 154q2 7 2.33 11.83.33 4.84.33 10.33 0 30.18-21.56 51.68-21.55 21.49-51.83 21.49-30.27 0-51.77-21.49-21.5-21.5-21.5-51.68 0-5.49.33-10.33.33-4.83 2.33-11.83L422-529.33q-7 2-11.83 2.33-4.84.33-10.34.33-1.83 0-21.83-2.66l-194 194q2 7 2.33 11.83.34 4.83.34 10.32 0 30.19-21.56 51.68-21.56 21.5-51.84 21.5Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 982 B |
1
resources/menu_arrow.svg
Normal file
1
resources/menu_arrow.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="40px" viewBox="0 -960 960 960" width="40px" fill="#5f6368"><path d="M400-280v-400l200 200-200 200Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 155 B |
Reference in New Issue
Block a user