Web Components- customElements/自定义标签之序列桢动画组件

本文介绍了如何使用Web组件技术创建一个自定义HTML标签,用于播放渲染序列帧,适用于本地互动数字媒体,特别适合单机版应用如展览展示。作者提供了代码示例和使用方法,包括配置路径、速率和帧数等。
摘要由CSDN通过智能技术生成

 创作灵感

前段时间碰到个用渲染序列桢替代3D的项目需求,然后手写一个基本的控制播放序列的功能。折腾几小时,因为是用vue开发的,所以单独写了个序列桢的播放组件传参调用。 虽然是可以用了但感觉每次这样感觉真麻烦。于是想到Web 组件可以自定义标签的功能,于是网上搜索了下自定义标签的基本用法,捣鼓了一个用来播放序列桢的标签。

呃,当然可能在线使用是个鸡肋功能(网络带宽原因序列图过大时会卡顿),只是工作关系,常用于开发本地互动数字媒体,用于单机版如展览展示等特殊需求上使用挺方便的。做了个粗糙的小样,给需要的人做个参考。

使用方法

        1. 把 anim-sequence.js 放在要引用的目录里

        2. 在html 文件里引用 anim-sequence.js . 

        3. 在要展示序列动画的地方,添加自定义的标签,配置好序列桢的路径、速率、总桢数就可运行。

        code:

            <t-animseq src="你的序列桢路径(不含自动增加的编号及扩展名)" total="250" rate="60" autoplay/>

    <t-animseq src="images/seq/xx_" total="250" rate="60" autoplay/>

        4. 注意src你的序列桢所在目录,如:images/seq/xx_0.jpg .... images/seq/xx_250.jpg  。 src的值为:images/seq/xx_ 。  扩展名默认为jpg ,如要修改png,添加属性:format="png"

代码

        index.html        

<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta name="description" content="自定义标签测试">
    <meta name="author" content="mythlong,阿爆野">
    <meta name="email" content="myth_long@qq.com"> 
	<title>自定义标签测试-序列桢动画标签</title> 
    <style>
    	html,body{
        height: 100%;
        margin: 0;
        overflow: hidden;
    	}
      body{
        background-color: #333;
      }
      .seq-con,.seq-con div{
        margin:2px; 
      }
    </style>
</head>
<body> 
  <!-- 
      example:
    <t-animseq src="../images/seq/dieluoji/" total="250" rate="60" manual onclick="toggle()"/>
      anual onclick="toggle()" 两个不能同时使用
      参数 说明: 
      total :总序列桢数  必填
      src : 序列桢的路径  必填
      format: 文件格式(jpg ,png),默认jpg.
      rate : 速率(1-60)  默认每少25桢, 
      autoplay :自动播放
      reverse :配合自动播放,反向播放
      manual : 手动左右拖动鼠标控制序列切换
      可用方法:play(),pause(),toggle(),next(),prev();
   -->

  <div class="seq-con" style="width: 49%;min-width: 256px;display: inline-block;color:#fff;">自动播放
    <t-animseq id="ani_seq1" src="../images/seq/dieluoji/" format="jpg" total="250" autoplay manual />
  </div>

  <div class="seq-con" style="width: 49%;min-width: 256px;display: inline-block;color:#fff;">点击播放
    <t-animseq id="ani_seq2" src="../images/seq/dieluoji/" total="250" rate="60" reverse onclick="toggle()" />
  </div>
 
  <div class="seq-con" style="color:#fff;">拖动播放
    <t-animseq id="ani_seq3" src="../images/seq/dieluoji/" total="250" manual/>
  </div>
  
  <script src="js/anim-sequence.js"></script> 
</body>
</html>

    anim-sequence.js

//author:mythlong
//email:myth_long@qq.com
//2024-01-06.
class AnimSeq extends HTMLElement {
    static get observedAttributes() {
        return ["src", "format", "total", "rate" ];
    }

    constructor() {
        super();
        this.interv=0;
        this.rate=25;
        this.fmt='jpg';
        this.cid=0;
        this.reverse=false;
        this.total=0;
        this.status='none';
        this.img=null;
        this.manual=false; 

        const shadow = this.attachShadow({ mode: "open" }); 
        const div = document.createElement("div");
        this.img = document.createElement("img"); 
        if (this.hasAttribute('format')) {
            this.fmt = this.getAttribute('format');
        }
        if (this.hasAttribute('total')) {
            this.total = this.getAttribute('total');
        }
        if (this.hasAttribute('rate')) {
            this.rate = this.getAttribute('rate');
        }
        if (this.hasAttribute('reverse')) {
            this.reverse = true;
        }
        if (this.hasAttribute('manual')) {
            this.manual = true;
        } 

        this.img.src = this.getAttribute('src') + this.cid +'.' + this.fmt;
        this.img.style.width = '100%';
        this.img.style.height = '100%';
        this.img.style.userSelect = 'none';
        div.style.userSelect = 'none';
        div.style.width = '100%';
        div.style.height = '100%'; 

        shadow.appendChild(div); 
        div.appendChild(this.img);

        this.dist=20;
        this.curX=0;
        this.canAct=false;

        if(this.manual){
        	this.fn=this.mouseupHander.bind(this);
        	this.addEventListener('mousedown',this.mousedownHander,false);
        	this.addEventListener('mousemove',this.mousemoveHander,false);
        	document.addEventListener('mouseup',this.fn,false);
        	this.interv=setInterval(()=>{
    			if(this.canAct){
    				this.img.src=this.getAttribute('src') + this.cid +'.' + this.fmt;
    			}
        	},20);
        }

    }

    mousedownHander(e){
    	e.preventDefault();
    	this.canAct=true;
    	this.curX=e.clientX;
    }

    mousemoveHander(e){ 
    	e.preventDefault();
    	if(this.canAct){
			this.cid=parseInt(this.cid)+Math.round(e.clientX-this.curX); 
    		if(this.cid>this.total){
    			this.cid=0;
        	}
        	else if(this.cid<0){
    			this.cid=this.total;
        	}
        	this.curX=e.clientX; 
    	}
    }

    mouseupHander(e){
    	this.canAct=false;
    	this.curX=e.clientX;
    } 

    connectedCallback() {
        if (this.hasAttribute('autoplay')) {
        	this.play();
        }
    }

    disconnectedCallback() {
        clearInterval(this.interv);
        if(this.manual){
        	this.removeEventListener('mousedown',this.mousedownHander);
        	this.removeEventListener('mousemove',this.mousemoveHander);
        	document.removeEventListener('mouseup',this.fn);
        }
    }


    play() {
        this.status='play';
        clearInterval(this.interv);
        this.interv=setInterval(()=>{ 
        	if(this.reverse){
        		this.cid--;
	        	if(this.cid<0){
	        		this.cid=this.total;
	        	}
        	}
        	else{
        		this.cid++;
        		if(this.cid>this.total){
        		this.cid=0;
	        	}
	        }
        	
        	this.img.src=this.getAttribute('src') + this.cid +'.' + this.fmt;
        },1000/this.rate);
    }
    pause() {
        this.status='pause';
        clearInterval(this.interv);
    }

    toggle(){    	
      if(this.status=='play'){
        this.pause(); 
      }
      else if(this.status!='play'){
        this.play(); 
      }
    }

    next(){    
		this.cid++;
		if(this.cid>this.total){
		this.cid=0;
    	} 	 
    	this.img.src=this.getAttribute('src') + this.cid +'.' + this.fmt;
    }

    prev(){ 
		this.cid--;
    	if(this.cid<0){
    		this.cid=this.total;
    	}    	 
    	this.img.src=this.getAttribute('src') + this.cid +'.' + this.fmt;
    }

}

customElements.define("t-animseq", AnimSeq);

在线演示

        PS:在线因为服务器带宽有限,展示卡顿。所以自己在本地上用序列测试为佳~

        自定义标签测试-序列桢动画标签

参考

Window: customElements property - Web APIs | MDN

HTML Standard

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

myth long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值