一.简介

直到现在,仍然不存在一项旨在网页上显示视频的标准。

今天,大多数视频是通过插件(比如 Flash)来显示的。然而,并非所有浏览器都拥有同样的插件。

HTML5 规定了一种通过 video 元素来包含视频的标准方法。如:

1
2
<video src="movie.ogg" controls="controls">
</video>

二.Canvas+Video

HTML5中引入新的元素canvas,其drawImage 方法允许在 canvas 中插入其他图像( img 和 canvas 元素) 。

drawImage函数有三种函数原型:

drawImage(image, dx, dy) 
drawImage(image, dx, dy, dw, dh) 
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

第一个参数image可以用HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement作为参数

dx和dy是image在canvas中定位的坐标值;dw和dh是image在canvas中即将绘制区域(相对dx和dy坐标的偏移量)的宽度和高度值;

sx和sy是image所要绘制的起始位置,sw和sh是image所要绘制区域(相对image的sx和sy坐标的偏移量)的宽度和高度值。

所以这使酷炫播放体验有了实现的可能。

三.理解canvas.translate和canvas.scale

很多人对于canvas.translate(x,y)的理解有的错误,之前一直以原点(0,0)为基准点,作用就是移动原点,默认的原点(0,0)是在屏幕左上角的,你可以通过translate(x,y)把点(x,y)作为原点,就一直以为这个(x,y)就是新的坐标原点。但看一下API就会知道,这种理解是不对的,

不过API确实容易误导大家:

1
2
3
4
5
6
7
view plain
public void translate (float dx, float dy) 
 Since: API Level 1 
Preconcat the current matrix with the specified translation 
Parameters 
dx  The distance to translate in X 
dy  The distance to translate in Y

其实是原来的原点分别在x轴和y轴偏移多远的距离,然后以偏移后的位置作为坐标原点。也就是说原来在(100,100),然后translate(1,1)新的坐标原点在(101,101)而不是(1,1)

canvas.scale:

canvas.scale提供了放大缩小倒置等功能。比如Y倒置:canvas.scale(1,-1)

四.核心代码

1
2
3
4
5
6
7
canvas.setAttribute('height', Math.floor(video.height));
      canvas.setAttribute('width', Math.floor(video.width));
 
      ctx.translate(0, canvas.height );
      ctx.scale(1, -1);
      ctx.globalAlpha = 0.3;
      ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height/2, canvas.width, canvas.height);

五.在线演示

 
 00:00 /

六.代码下载

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<html >
<head>
<meta charset="utf-8" />
<title></title>
 
</head>
<body>
   <div>
   <video  width="640" height="264">
  </video> <br/>
  <canvas style="position:absolute; top:143px;"></canvas>
</div>
<div  style="position:absolute; top:400px;">
  <p>
    <input type="button" id="play" value="play">
    <span id="position">00:00</span> / <span id="duration"></span>
  </p>
  </div>
<script >
 
    var addEvent = (function () {
        if (document.addEventListener) {
            return function (el, type, fn) {
                if (el && el.nodeName || el === window) {
                    el.addEventListener(type, fn, false);
                } else if (el && el.length) {
                    for (var i = 0; i < el.length; i++) {
                        addEvent(el[i], type, fn);
                    }
                }
            };
        } else {
            return function (el, type, fn) {
                if (el && el.nodeName || el === window) {
                    el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
                } else if (el && el.length) {
                    for (var i = 0; i < el.length; i++) {
                        addEvent(el[i], type, fn);
                    }
                }
            };
        }
    })();
    
</script>
<script>
    var video = document.querySelector('video');
    var togglePlay = document.querySelector('#play');
    var position = document.querySelector('#position');
    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
 
    addEvent(togglePlay, 'click', function () {
        video.playbackRate = 0.5;
        if (video.paused) {
            if (video.ended) video.currentTime = 0;
            video.play();
            this.value = "pause";
        } else {
            video.pause();
            this.value = "play";
        }
    });
 
    setInterval(function () {
        position.innerHTML = asTime(video.currentTime);
        ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height / 2, canvas.width, canvas.height);
    }, 1000 / 15);
 
    addEvent(video, 'ended', function () {
        togglePlay.value = "play";
    });
 
    addEvent(video, 'canplay', function () {
        video.muted = true;
        document.querySelector('#duration').innerHTML = asTime(this.duration);
        startCanvas();
    });
 
 
    function startCanvas() {
        canvas.setAttribute('height', Math.floor(video.height));
        canvas.setAttribute('width', Math.floor(video.width));
 
        ctx.translate(0, canvas.height );
        ctx.scale(1, -1);
        ctx.globalAlpha = 0.3;
        ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height/2, canvas.width, canvas.height);
 
       
    }
 
    function asTime(t) {
        t = Math.round(t);
        var s = t % 60;
        var m = Math.round(t / 60);
 
        return two(m) + ':' + two(s);
    }
 
    function two(s) {
        s += "";
        if (s.length < 2) s = "0" + s;
        return s;
    }
</script>
</body>
 
</html>

Canvas+Video打造酷炫播放体验的更多相关文章

  1. 使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突

    使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静 ...

  2. HTML5 Canvas玩转酷炫大波浪进度图

    如上图所见,本文就是要实现上面那种效果. 由于最近AlloyTouch要写一个下拉刷新的酷炫loading效果.所以首选大波浪进度图. 首先要封装一下大波浪图片进度组件.基本的原理是利用Canvas绘 ...

  3. 三分钟学会用 js + css3 打造酷炫3D相册

    之前发过该文,后来不知怎么回事不见了,现在重新发一下. 中秋主题的3D旋转相册 如图,这是通过Javascript和css3来实现的.整个案例只有不到80行代码,我希望通过这个案例,让正处于迷茫期的j ...

  4. MVC中使用SignalR打造酷炫实用的即时通讯功能附源码

    前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯.由于当时走的太急,忘记把代码拿出来.想想这已经是大半年前的事情了,时间过 ...

  5. MVC中使用SignalR打造酷炫实用的即时通讯功能(轉載)

    資料來源:http://www.fangsi.net/1144.html 前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯 ...

  6. 学习websocket-SignalR,MVC中使用SignalR打造酷炫实用的即时通讯

    http://www.cnblogs.com/Leo_wl/p/4793284.html http://www.fangsi.net/archives/1144.html

  7. Android 使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突

    如果你还在为处理滑动冲突而发愁,那么你需要静下心来看看这边文章,如果你能彻底理解这篇文章中使用的技术,那么,一切滑动冲突的问题解决起来就轻而易举了: 先扔一个最终实现的效果图 先分析下效果图中实现的功 ...

  8. [刘阳Java]_酷炫视频播放器制作_界面篇

    今天开始分享一篇酷炫播放器制作,包括界面+JS.整个案例非常类似腾讯视频,优酷视频,爱奇艺视频.我们先看一下效果图,然后这篇文章主要界面篇 是不是效果比较酷炫,那么我接着来给大家说一下这个界面设计思路 ...

  9. 2019基于Hexo快速搭建个人博客,打造一个炫酷博客(1)-奥怪的小栈

    本文转载于:奥怪的小栈 这篇文章告诉你如何在2019快速上手搭建一个像我一样的博客:基于HEXO+Github搭建.并完成SEO优化,打造一个炫酷博客. 本站基于HEXO+Github搭建.所以你需要 ...

随机推荐

  1. 电脑每次开机都出现check file system on:C 的解决办法

    电脑每次开机都出现check file system on:C 的解决办法... ----------------------------------------- ----------------- ...

  2. 用IO流中的File类来创建文件及目录

    题目如下: 设计一个命令窗口程序,要求按照如下的格式显示 例如:===利用命令窗口完成文件的操作===(1)创建目录 (2)创建文件 (3)删除目录 (4)删除文件 ===现在正在做创建目录的操作== ...

  3. redis实现消息队列

    业务需求 本文是以laravel框架来介绍redis队列,具体用法你可以参考http://www.cnblogs.com/lengthuo/p/7277260.html最近接受一个很简单的东西,(说起 ...

  4. RPC框架实现思路浅析

    第一部分,设计分析 远程调用要解决的主要问题: 1,序列化 : 如何将对象转化为二进制数据进行传输,如何将二进制数据转化对象 2,数据的传输(协议,第三方框架) 3,服务的注册/发现,单点故障,分布式 ...

  5. 2017最新的Python教程分享

    Python在数据科学盛行的今天,其易于阅读和编写的特点,越来越受编程者追捧.在IEEE发布的2017年编程语言排行榜中,Python也高居首位.如果你有学Python的计划,快来看看小编分享的Pyt ...

  6. 深入理解计算机系统(1.1)------Hello World 是如何运行的

    上一篇序章我谈了谈 程序员为啥要懂底层计算机结构 ,有人赞同也有人反对,但是这并不影响 LZ 对深入理解计算机系统研究的热情.这篇博客以案例驱动的模式,通过跟踪一个简单 Hello World 程序的 ...

  7. 基于大数据的电影网站项目开发之CentOS的安装(一)

    一.下载VMware并安装,至于安装教程从网上搜索进行参考 二.下载系统镜像文件,这里使用的是CentOS-6.5-x86_64-bin-DVD1.iso 三.安装镜像文件 运行VMware work ...

  8. Day-8: 面对对象编程

    面对过程的程序设计方法意在将函数分成子函数,再依次调用这些函数来解决问题. 而面对对象的程序设计方法,来源于自然界,类是实例的抽象,实例是类的具体.自定义出来的对象是类,而所有的数据都可以看成是对象, ...

  9. [转载]C header files matching your running 

    原文地址:C header files matching your running kernel were not found.作者:[Opser]小默 c header files matching ...

  10. 终于知道如何使Tab控件的不出现白边的方法了

    如下图,在棋盘右侧添加了Tab控件,做成属性页的样子,但出现了白边,很不美观: 后来发现,需要把Tab空间的Owner Draw Fixed 设置为TRUE.但问题又来了,属性页上的标题文字不显示了, ...