q-import { dist/q-components/q-vid-player.qhtml }
div.visual-shell {
div.viewport {
q-vid-player hudExtendPlayer {
src: "tools/assets/hud-extend.qvid"
frameDuration: 16
scale: 1
reverse: false
repeat: true
startFrame: 0
endFrame: 0
onstepped(currentFrame) {
if (typeof window.__qvidVisualFrameStepped === "function") {
window.__qvidVisualFrameStepped(currentFrame);
}
}
}
}
div.controls {
button {
id: "qvid-start-button"
type: "button"
onclick {
document.querySelector("q-vid-player").start();
}
text { Start }
}
button {
id: "qvid-stop-button"
type: "button"
onclick {
document.querySelector("q-vid-player").stop();
}
text { Stop }
}
button {
id: "qvid-step-button"
type: "button"
onclick {
document.querySelector("q-vid-player").step();
}
text { Step }
}
button {
id: "qvid-reverse-button"
type: "button"
text { Reverse }
}
button {
id: "qvid-repeat-button"
type: "button"
text { Repeat }
}
button {
id: "qvid-scale-down-button"
type: "button"
text { Scale - }
}
button {
id: "qvid-scale-up-button"
type: "button"
text { Scale + }
}
div.readout {
span#qvid-status { text { loading } }
span#qvid-frame { text { frame: 0 } }
span#qvid-mode { text { forward repeat } }
span#qvid-scale { text { scale: 1 } }
}
}
div.property-panel {
div.property-grid {
div.field.src-field {
label { for: "qvid-src-input" text { src } }
input#qvid-src-input {
type: "text"
value: "tools/assets/hud-extend.qvid"
}
}
div.field {
label { for: "qvid-frame-duration-input" text { frameDuration ms } }
input#qvid-frame-duration-input {
type: "number"
min: "1"
step: "1"
value: "16"
}
}
div.field {
label { for: "qvid-scale-input" text { scale } }
input#qvid-scale-input {
type: "number"
min: "0.1"
step: "0.05"
value: "1"
}
}
div.field {
label { for: "qvid-current-frame-input" text { currentFrame } }
input#qvid-current-frame-input {
type: "number"
min: "0"
step: "1"
value: "0"
}
}
div.field {
label { for: "qvid-start-frame-input" text { startFrame } }
input#qvid-start-frame-input {
type: "number"
min: "0"
step: "1"
value: "0"
}
}
div.field {
label { for: "qvid-end-frame-input" text { endFrame } }
input#qvid-end-frame-input {
type: "number"
min: "0"
step: "1"
value: "0"
}
}
div.check-field {
span { text { reverse } }
input#qvid-reverse-input { type: "checkbox" }
}
div.check-field {
span { text { repeat } }
input#qvid-repeat-input {
type: "checkbox"
checked: true
}
}
div.field.frame-slider {
label { for: "qvid-frame-slider" text { currentFrame slider } }
input#qvid-frame-slider {
type: "range"
min: "0"
max: "0"
step: "1"
value: "0"
}
}
}
}
}
onReady {
var status = document.querySelector("#qvid-status");
var frame = document.querySelector("#qvid-frame");
var mode = document.querySelector("#qvid-mode");
var scale = document.querySelector("#qvid-scale");
var qhtmlHost = document.querySelector("q-html");
var startButton = document.querySelector("#qvid-start-button");
var stopButton = document.querySelector("#qvid-stop-button");
var stepButton = document.querySelector("#qvid-step-button");
var reverseButton = document.querySelector("#qvid-reverse-button");
var repeatButton = document.querySelector("#qvid-repeat-button");
var scaleDownButton = document.querySelector("#qvid-scale-down-button");
var scaleUpButton = document.querySelector("#qvid-scale-up-button");
var srcInput = document.querySelector("#qvid-src-input");
var durationInput = document.querySelector("#qvid-frame-duration-input");
var scaleInput = document.querySelector("#qvid-scale-input");
var currentFrameInput = document.querySelector("#qvid-current-frame-input");
var startFrameInput = document.querySelector("#qvid-start-frame-input");
var endFrameInput = document.querySelector("#qvid-end-frame-input");
var reverseInput = document.querySelector("#qvid-reverse-input");
var repeatInput = document.querySelector("#qvid-repeat-input");
var frameSlider = document.querySelector("#qvid-frame-slider");
function asBoolean(value, fallbackValue) {
if (value === true || value === false) {
return value;
}
var text = String(value == null ? "" : value).toLowerCase();
if (text === "true" || text === "1" || text === "yes" || text === "on") {
return true;
}
if (text === "false" || text === "0" || text === "no" || text === "off") {
return false;
}
return Boolean(fallbackValue);
}
function numberFromInput(input, fallbackValue) {
var value = input ? Number(input.value) : Number.NaN;
return Number.isFinite(value) ? value : fallbackValue;
}
function currentPlayer() {
return document.querySelector("q-vid-player");
}
function updateMode() {
var player = currentPlayer();
var isReverse = asBoolean(player ? player.reverse : false, false);
var isRepeat = asBoolean(player ? player.repeat : true, true);
if (mode) {
mode.textContent = (isReverse ? "reverse" : "forward") + " " + (isRepeat ? "repeat" : "once");
}
if (scale) {
scale.textContent = "scale: " + String(player ? player.scale : 1);
}
}
window.__qvidVisualFrameStepped = function(currentFrame) {
if (frame) {
frame.textContent = "frame: " + String(currentFrame);
}
if (currentFrameInput && document.activeElement !== currentFrameInput) {
currentFrameInput.value = String(currentFrame);
}
if (frameSlider && document.activeElement !== frameSlider) {
frameSlider.value = String(currentFrame);
}
updateMode();
};
function syncInputs() {
var player = currentPlayer();
if (srcInput) {
srcInput.value = String(player && player.src || "");
}
if (durationInput) {
durationInput.value = String(player && player.frameDuration || 16);
}
if (scaleInput) {
scaleInput.value = String(player && player.scale || 1);
}
if (currentFrameInput) {
currentFrameInput.value = String(player && player.currentFrame || 0);
}
if (frameSlider) {
frameSlider.value = String(player && player.currentFrame || 0);
}
if (startFrameInput) {
startFrameInput.value = String(player && player.startFrame || 0);
}
if (endFrameInput) {
endFrameInput.value = String(player && player.endFrame || 0);
}
if (reverseInput) {
reverseInput.checked = asBoolean(player && player.reverse, false);
}
if (repeatInput) {
repeatInput.checked = asBoolean(player && player.repeat, true);
}
updateMode();
}
function bindEvent(node, eventName, callback) {
if (node) {
node.addEventListener(eventName, callback);
}
}
bindEvent(startButton, "click", function() {
var player = currentPlayer();
if (player) { player.start(); }
});
bindEvent(stopButton, "click", function() {
var player = currentPlayer();
if (player) { player.stop(); }
});
bindEvent(stepButton, "click", function() {
var player = currentPlayer();
if (player) { player.step(); }
});
bindEvent(reverseButton, "click", function() {
var player = currentPlayer();
if (player) {
player.reverse = !asBoolean(player.reverse, false);
syncInputs();
}
});
bindEvent(repeatButton, "click", function() {
var player = currentPlayer();
if (player) {
player.repeat = !asBoolean(player.repeat, true);
syncInputs();
}
});
bindEvent(scaleDownButton, "click", function() {
var player = currentPlayer();
if (player) {
player.scale = Math.max(0.25, Number(player.scale || 1) - 0.25);
syncInputs();
}
});
bindEvent(scaleUpButton, "click", function() {
var player = currentPlayer();
if (player) {
player.scale = Number(player.scale || 1) + 0.25;
syncInputs();
}
});
bindEvent(srcInput, "change", function() {
var player = currentPlayer();
if (!player) { return; }
player.stop();
player.src = srcInput.value;
});
bindEvent(durationInput, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.frameDuration = Math.max(1, Math.floor(numberFromInput(durationInput, 16)));
updateMode();
});
bindEvent(scaleInput, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.scale = Math.max(0.1, numberFromInput(scaleInput, 1));
updateMode();
});
bindEvent(currentFrameInput, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.currentFrame = Math.max(0, Math.floor(numberFromInput(currentFrameInput, 0)));
});
bindEvent(frameSlider, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.currentFrame = Math.max(0, Math.floor(numberFromInput(frameSlider, 0)));
});
bindEvent(startFrameInput, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.startFrame = Math.max(0, Math.floor(numberFromInput(startFrameInput, 0)));
});
bindEvent(endFrameInput, "input", function() {
var player = currentPlayer();
if (!player) { return; }
player.endFrame = Math.max(0, Math.floor(numberFromInput(endFrameInput, 0)));
});
bindEvent(reverseInput, "change", function() {
var player = currentPlayer();
if (!player) { return; }
player.reverse = Boolean(reverseInput.checked);
updateMode();
});
bindEvent(repeatInput, "change", function() {
var player = currentPlayer();
if (!player) { return; }
player.repeat = Boolean(repeatInput.checked);
updateMode();
});
bindEvent(qhtmlHost, "q-vid-load", function(event) {
var player = currentPlayer();
var maxFrame = Math.max(0, Number(event.detail.frameCount || 1) - 1);
if (status) {
status.innerHTML = "loaded " + String(event.detail.width || 0) + "x" + String(event.detail.height || 0);
}
if (currentFrameInput) {
currentFrameInput.max = String(maxFrame);
}
if (startFrameInput) {
startFrameInput.max = String(maxFrame);
}
if (endFrameInput) {
endFrameInput.max = String(maxFrame);
if (String(endFrameInput.value || "0") === "0") {
endFrameInput.value = String(maxFrame);
player.endFrame = maxFrame;
}
}
if (frameSlider) {
frameSlider.max = String(maxFrame);
}
syncInputs();
});
bindEvent(qhtmlHost, "q-vid-error", function(event) {
if (status) {
status.textContent = event.detail.error && event.detail.error.message ? event.detail.error.message : "q-vid load error";
}
});
bindEvent(qhtmlHost, "q-vid-started", function() {
if (status) {
status.innerHTML = "playing";
}
});
bindEvent(qhtmlHost, "q-vid-stopped", function() {
if (status) {
status.textContent = "stopped";
}
});
syncInputs();
}