web版本的视频video标签缩放项目

  • 支持 mp4 flv m3u8等视频播放
  • 支持任意缩放比例的鼠标手势,以及在缩放条件的拖拽手势
  • 支持最大化下的视频缩放
  • 当前进度标签的定义属性
  • 支持步进缩略图
  • 全面超越xgplayer
  • 工业化场景适用
  • 100%还原视频影像

 

已经开源 项目地址

马良/vediozoom web版本的视频放大组件

 

 影片为

《网络谜踪2》索尼

 

部分项目截图

 全屏模式

 

 

项目参考

Canvas鼠标滚轮缩放以及画布拖动(图文并茂版)本文会带大家认识Canvas中常用的坐标变换方法 translate - 掘金

GitHub - astonishqft/scanvas-translate-and-scale: Canvas画布实现鼠标滚轮缩放和画布拖动

部分源代码的参考

复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Canvas鼠标滚轮缩放和拖放</title>
  <style>
    canvas {
      border: solid 1px #000;
      margin: 0px auto;
      display: block;
    }
    .options {
      display: flex;
      justify-content: center;
      height: 44px;
      align-items: center;
    }
    button {
      margin-left: 15px;
    }
  </style>
</head>

<body>
  <div class="options">
    <button onclick="zoomIn()">放大 +</button>
    <button onclick="zoomOut()">缩小 -</button>
    <button onclick="reset()">还原</button>
  </div>
  <canvas id="canvas"></canvas>
  <script>
    class Scene {
      offset = { x: 0, y: 0 }; // 拖动偏移
      curOffset = { x: 0, y: 0 }; // 记录上一次的偏移量
      mousePosition = { x: 0, y: 0 }; // 记录鼠标滚轮点击时的坐标位置
      maxScale = 8;
      minScale = 0.4;
      scaleStep = 0.2;
      scale = 1;
      preScale = 1;

      x = 0; // 记录鼠标点击Canvas时的横坐标
      y = 0; // 记录鼠标点击Canvas时的纵坐标

      constructor(id, options = {
        width: 600,
        height: 400
      }) {
        this.canvas = document.querySelector('#' + id)
        this.width = options.width;
        this.height = options.height;
        this.canvas.width = options.width;
        this.canvas.height = options.height;
        this.ctx = this.canvas.getContext('2d');

        this.onMousedown = this.onMousedown.bind(this);
        this.onMousemove = this.onMousemove.bind(this);
        this.onMouseup = this.onMouseup.bind(this);
        this.onMousewheel = this.onMousewheel.bind(this);
        this.canvas.addEventListener('mousewheel', this.onMousewheel);
        this.canvas.addEventListener('mousedown', this.onMousedown);
      }

      onMousewheel(e) {
        e.preventDefault();

        this.mousePosition.x = e.offsetX; // 记录当前鼠标点击的横坐标
        this.mousePosition.y = e.offsetY; // 记录当前鼠标点击的纵坐标
        if (e.wheelDelta > 0) {
          // 放大
          this.scale = parseFloat((this.scaleStep + this.scale).toFixed(2)); // 解决小数点运算丢失精度的问题
          if (this.scale > this.maxScale) {
            this.scale = this.maxScale;
            return;
          }
        } else {
          // 缩小
          this.scale = parseFloat((this.scale - this.scaleStep).toFixed(2)); // 解决小数点运算丢失精度的问题
          if (this.scale < this.minScale) {
            this.scale = this.minScale;
            return;
          }
        }

        this.zoom();
      }

      zoom() {
        this.offset.x = this.mousePosition.x - (this.mousePosition.x - this.offset.x) * this.scale / this.preScale;
        this.offset.y = this.mousePosition.y - (this.mousePosition.y - this.offset.y) * this.scale / this.preScale;

        this.paint(this.ctx);
        this.preScale = this.scale;
        this.curOffset.x = this.offset.x;
        this.curOffset.y = this.offset.y;
      }

      onMousedown(e) {
        if (e.button === 0) {
          // 鼠标左键
          this.x = e.x;
          this.y = e.y
          window.addEventListener('mousemove', this.onMousemove);
          window.addEventListener('mouseup', this.onMouseup)
        }
      }

      onMousemove(e) {
       this.offset.x = this.curOffset.x + (e.x - this.x);
       this.offset.y = this.curOffset.y + (e.y - this.y);

       this.paint();
      }

      onMouseup() {
        this.curOffset.x = this.offset.x;
        this.curOffset.y = this.offset.y;
        window.removeEventListener('mousemove', this.onMousemove);
        window.removeEventListener('mouseup', this.onMouseup);
      }

      zoomIn() {
        this.scale += this.scaleStep;
        if (this.scale > this.maxScale) {
          this.scale = this.maxScale;
          return;
        }
        this.mousePosition.x = this.width / 2;
        this.mousePosition.y = this.height / 2;
        this.zoom();
      }

      zoomOut() {
        this.scale -= this.scaleStep;
        if (this.scale < this.minScale) {
          this.scale = this.minScale;
          return;
        }
        this.mousePosition.x = this.width / 2;
        this.mousePosition.y = this.height / 2;
        this.zoom();
      }

      // 重置
      reset = function () {
        this.clear();
        this.scale = 1; // 当前缩放
        this.preScale = 1; // 上一次缩放
        this.offset = { x: 0, y: 0 }; // 拖动偏移
        this.curOffset = { x: 0, y: 0 }; // 当前偏移
        this.mousePosition = { x: 0, y: 0 };
        this.draw();
      };

      draw() {
        this.ctx.fillStyle = 'red';
        this.ctx.fillRect(50, 50, 50, 50);

        this.ctx.fillStyle = 'green';
        this.ctx.fillRect(150, 150, 50, 50);
      }

      clear() {
        this.canvas.width = this.width;
      }

      paint() {
        this.clear();
        this.ctx.translate(this.offset.x, this.offset.y);
        this.ctx.scale(this.scale, this.scale);
        this.draw();
      }
    }

    let scene = new Scene('canvas');

    scene.draw();

    // 放大
    function zoomIn() {
      scene.zoomIn();
    }

    // 缩小
    function zoomOut() {
      scene.zoomOut();
    }

    // 还原
    function reset() {
      scene.reset();
    }
  </script>
</body>

</html>
复制代码

 

posted on   漫思  阅读(29)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
历史上的今天:
2024-02-19 c# WPF 布局控件
2024-02-19 C# 12 中的新增功能
2023-02-19 10年磨一剑,.net 公共类库,终于初版
2019-02-19 回车登录页面的问题

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示