Files
ArtPlayer/docs/compiled/artplayer-plugin-chapter.mjs
T
Harvey Zhao 699bf09577 feat: update changelog with Parcel to Vite refactor
feat: add danmuku plugin documentation and i18n setup guide

- Created a new documentation file for the danmuku plugin with code examples.
- Added a comprehensive guide for language settings (i18n) including default languages, importing languages, adding new languages, and modifying existing languages.
- Included code snippets for initializing the Artplayer with different language settings.

Add internationalization support for multiple languages in Artplayer

- Introduced Arabic (ar), Czech (cs), Spanish (es), Persian (fa), French (fr), Indonesian (id), Polish (pl), Russian (ru), Turkish (tr), Vietnamese (vi), and Traditional Chinese (zh-tw) translations.
- Created corresponding JavaScript and ES module files for each language containing translated strings for player controls and settings.
- Added a new documentation file for language settings in the project.

feat: add initial implementation of start option page with interactive code execution buttons

feat: add danmuku plugin documentation and i18n setup guide

- Created a new documentation file for the danmuku plugin, providing code examples for usage.
- Added a comprehensive guide for language settings, including default languages, importing languages, adding new languages, and modifying existing languages.
- Included code snippets for initializing the Artplayer with different language settings and importing language files.

refactor: update danmuku worker implementation and remove unused i18n files

- Changed the way the Danmuku class creates a Web Worker by using a worker loader instead of creating a blob.
- Removed Arabic, Czech, Spanish, Persian, French, Indonesian, Polish, Russian, Turkish, Vietnamese, and Traditional Chinese i18n files as they are no longer needed.
- Updated the Vite build configuration to disable banners for inline workers and added a plugin to remove worker banners from generated code.

feat: add danmuku plugin and i18n setup documentation

- Created a new documentation file for the danmuku plugin, providing code examples for usage.
- Added a new documentation file for language settings (i18n), detailing how to set default languages, import languages, and add new languages.
- Included code snippets for initializing the Artplayer with different language settings and examples for modifying existing languages.

feat: add danmuku plugin and i18n setup documentation

- Created a new documentation file for the danmuku plugin with code examples.
- Added a new documentation file for language settings (i18n) including import instructions and examples for setting default and custom languages.
- Updated the i18n documentation to include details on adding and modifying languages.

feat: add danmuku plugin and i18n setup documentation

- Created a new JavaScript file for the danmuku plugin documentation with multiple code execution buttons.
- Added a new JavaScript file for i18n (internationalization) setup documentation, including instructions for language settings, importing languages, and modifying language options.
- Included examples for setting default languages and adding new languages in the i18n documentation.

Refactor code structure for improved readability and maintainability
2026-03-07 15:21:34 +08:00

163 lines
7.4 KiB
JavaScript

/*!
* artplayer-plugin-chapter.js v1.0.3
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
const style = ".artplayer-plugin-chapter .art-control-progress-inner{height:100%!important;background-color:transparent!important}.artplayer-plugin-chapter .art-control-progress-inner>.art-progress-hover,.artplayer-plugin-chapter .art-control-progress-inner>.art-progress-loaded,.artplayer-plugin-chapter .art-control-progress-inner>.art-progress-played{display:none!important}.artplayer-plugin-chapter .art-control-thumbnails{bottom:calc(var(--art-bottom-gap) + 64px)!important}.artplayer-plugin-chapter .art-chapters{position:absolute;z-index:0;inset:0;display:flex;align-items:center;gap:4px;height:100%;transform:scaleY(1.25)}.artplayer-plugin-chapter .art-chapters .art-chapter{display:flex;align-items:center;height:100%}.artplayer-plugin-chapter .art-chapters .art-chapter .art-chapter-inner{position:relative;cursor:pointer;width:100%;height:50%;border-radius:10px;overflow:hidden;transition:height var(--art-transition-duration) ease;background-color:var(--art-progress-color)}.artplayer-plugin-chapter .art-chapters .art-chapter:hover .art-chapter-inner{height:100%}.artplayer-plugin-chapter .art-chapter-title{transform-origin:bottom center;transform:scale(.5);opacity:0;position:absolute;z-index:70;top:-50px;left:0;padding:3px 5px;line-height:1;font-size:14px;border-radius:var(--art-border-radius);white-space:nowrap;background-color:var(--art-tip-background);transition:transform var(--art-transition-duration) ease,opacity var(--art-transition-duration) ease}.artplayer-plugin-chapter.art-progress-hover .art-chapter-title{transform:scale(1);opacity:1}";
function artplayerPluginChapter(option = {}) {
return (art) => {
const { $player } = art.template;
const { setStyle, append, clamp, query, addClass, removeClass } = art.constructor.utils;
const html = `
<div class="art-chapter">
<div class="art-chapter-inner">
<div class="art-progress-hover"></div>
<div class="art-progress-loaded"></div>
<div class="art-progress-played"></div>
</div>
</div>
`;
let $chapters = [];
const $inner = art.query(".art-control-progress-inner");
const $control = append($inner, '<div class="art-chapters"></div>');
const $title = append($inner, '<div class="art-chapter-title"></div>');
function showTitle({ $chapter, width }) {
const title = $chapter.dataset.title.trim();
if (title) {
$title.textContent = title;
const titleWidth = $title.clientWidth;
if (width <= titleWidth / 2) {
setStyle($title, "left", 0);
} else if (width > $inner.clientWidth - titleWidth / 2) {
setStyle($title, "left", `${$inner.clientWidth - titleWidth}px`);
} else {
setStyle($title, "left", `${width - titleWidth / 2}px`);
}
}
}
function update(chapters = []) {
$chapters = [];
$control.textContent = "";
removeClass($player, "artplayer-plugin-chapter");
if (!Array.isArray(chapters))
return;
if (!chapters.length)
return;
if (!art.duration)
return;
chapters = chapters.sort((a, b) => a.start - b.start);
for (let i = 0; i < chapters.length; i++) {
const chapter = chapters[i];
const nextChapter = chapters[i + 1];
if (chapter.end === Infinity) {
chapter.end = art.duration;
}
if (typeof chapter.start !== "number" || typeof chapter.end !== "number" || typeof chapter.title !== "string") {
throw new TypeError("Illegal chapter data type");
}
if (chapter.start < 0 || chapter.end > art.duration || chapter.start >= chapter.end) {
throw new Error("Illegal chapter time point");
}
if (nextChapter && chapter.end > nextChapter.start) {
throw new Error("Illegal chapter time point");
}
}
if (chapters[0].start > 0) {
chapters.unshift({ start: 0, end: chapters[0].start, title: "" });
}
if (chapters[chapters.length - 1].end < art.duration) {
chapters.push({ start: chapters[chapters.length - 1].end, end: art.duration, title: "" });
}
for (let i = 0; i < chapters.length - 1; i++) {
if (chapters[i].end !== chapters[i + 1].start) {
chapters.splice(i + 1, 0, {
start: chapters[i].end,
end: chapters[i + 1].start,
title: ""
});
}
}
$chapters = chapters.map((chapter) => {
const $chapter = append($control, html);
const start = clamp(chapter.start, 0, art.duration);
const end = clamp(chapter.end, 0, art.duration);
const duration = end - start;
const percentage = duration / art.duration;
$chapter.dataset.start = start;
$chapter.dataset.end = end;
$chapter.dataset.duration = duration;
$chapter.dataset.title = chapter.title.trim();
$chapter.style.width = `${percentage * 100}%`;
return {
$chapter,
$hover: query(".art-progress-hover", $chapter),
$loaded: query(".art-progress-loaded", $chapter),
$played: query(".art-progress-played", $chapter)
};
});
addClass($player, "artplayer-plugin-chapter");
art.emit("setBar", "loaded", art.loaded || 0);
}
art.on("setBar", (type, percentage) => {
if (!$chapters.length)
return;
for (let i = 0; i < $chapters.length; i++) {
const { $chapter, $loaded, $played, $hover } = $chapters[i];
const $target = {
hover: $hover,
loaded: $loaded,
played: $played
}[type];
if (!$target)
return;
const width = $control.clientWidth * percentage;
const currentTime = art.duration * percentage;
const duration = Number.parseFloat($chapter.dataset.duration);
const start = Number.parseFloat($chapter.dataset.start);
const end = Number.parseFloat($chapter.dataset.end);
if (currentTime < start) {
setStyle($target, "width", 0);
}
if (currentTime > end) {
setStyle($target, "width", "100%");
}
if (currentTime >= start && currentTime <= end) {
const percentage2 = (currentTime - start) / duration;
setStyle($target, "width", `${percentage2 * 100}%`);
if (type === "hover" && width > 0) {
showTitle({ $chapter, width });
}
}
}
});
art.once("video:loadedmetadata", () => update(option.chapters));
return {
name: "artplayerPluginChapter",
update: ({ chapters }) => update(chapters)
};
};
}
if (typeof document !== "undefined") {
const id = "artplayer-plugin-chapter";
let $style = document.getElementById(id);
if (!$style) {
$style = document.createElement("style");
$style.id = id;
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
document.head.appendChild($style);
});
} else {
(document.head || document.documentElement).appendChild($style);
}
}
$style.textContent = style;
}
if (typeof window !== "undefined") {
window.artplayerPluginChapter = artplayerPluginChapter;
}
export {
artplayerPluginChapter as default
};