精华内容
下载资源
问答
  • 图片基础知识

    2019-05-23 09:59:22
    一、YUV 是一种颜色编码方法。...2、各个字母代表的含义 Y 表示明亮度,即我们说灰度值。 U 表示色度 V 表示浓度 值得一提是,Y分量可以黑白电视机所有影像信息。 3、常用YUV格式 YUV表...

    一、YUV

    是一种颜色编码方法。通常使用在各个视频处理组件中。YUV的原理是把亮度与色度分离。

    1、使用YUV的优点

    1. 彩色YUV图像转黑白YUV图像转换非常的简单,这一特性用在电视信号上。
    2. YUV数据总尺寸小于RGB格式。

    2、各个字母代表的含义

    Y 表示明亮度,即我们说的灰度值。
    U 表示色度
    V 表示浓度

    值得一提的是,Y分量可以黑白电视机的所有影像信息。

    3、常用的YUV格式

    YUV的表示法称为A:B:C表示法:

    1. 4:4:4 表示完全取样。
    2. 4:2:2表示2:1的水平取样,没有垂直下采样。
    3. 4:2:0表示2:1的水平取样。
    4. 4:1:1表示4:1的水平取样,没用垂直下采样。

    最常用Y:UV记录的比重通常为1:1或者2:1,DVD-Video是以YUV4:2:0的方式记录,也就是我们俗称的I420。

    4、转换

    YUV420P,Y,U,V三个分量都是平面格式,分为I420和YV12。I420格式和YV12格式的不同处在U平面和V平面的位置不同。在I420格式中,U平面紧跟在Y平面之后,然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。

    YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。
    I420: YYYYYYYY UU VV =>YUV420P
    YV12: YYYYYYYY VV UU =>YUV420P
    NV12: YYYYYYYY UV UV =>YUV420SP
    NV21: YYYYYYYY VU VU =>YUV420SP

    1、NV21转NV12

    private void swapNV21ToNV12(byte[] nv21, byte[] nv12, int width, int height){
    	if(nv21 == NULL || nv12 == NULL)
    		return ;
    	System.arraycopy(nv21 ,  0 , nv12 , 0 , framezie);
    	for(int j  = 0 ;  j < framesize / 2 ; j += 2){
    		nv12[framesize + j + 1] = nv21[j + framesize];
    		nv12[framesize + j] = nv21[j + framesize + 1];
    	}
    }
    

    2、YV12转I420

     private void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width, int height){
    	System.arraycopy(yv12bytes , 0 , i420bytes , 0 , width * height);
    	System.arraycopy(yu12bytes , width * height + widhth * height  / 4 , i420bytes , width * height , width*height/4 );
    	System.arraycopy(yv12bytes, width*height, i420bytes,width*height+width*height/4,width*height/4);
    }
    

    3、yv12转nv12

     void swapYV12toNV12(byte[] yv12bytes, byte[] nv12bytes, int width,int height){
     	int nLenV = width * height;
     	int nLenU = nLenY / 4;
     	System.arraycopy(yv12bytes , 0 , nv12bytes , 0 , width * height);
     	for(int i = 0 ; i < nLenU ; i++){
    		nv12bytes[nLenY + 2 * i + 1] = yv12bytes[nLenY + i];
    		nv12bytes[nLenY + 2 * i]=yv12bytes[nLenY + nLenU +i];
    	}
     }
    

    4、nv12转I420

     void swapNV12toI420(byte[] nv12bytes, byte[] i420bytes, int width,int height){
     	    int nLenY = width * height;
      	    int nLenU = nLenY/4;
      	    System.arraycopy(nv12bytes, 0, i420bytes, 0, width*height);
      	    for(int i = 0 ; i < nLenU ; i++){
    			i420bytes[nLenY+i] = nv12bytes[nLenY+2*i+1];
    			i420bytes[nLenY+nLenU+i] = nv12bytes[nLenY+2*i];
    		}
     }
    

    4、YUV图解

    图片来自网络

    • 图片来自网络
      YUV 4:4:4采样,每一个Y对应一组UV分量。
      YUV 4:2:2采样,每两个Y共用一组UV分量。
      YUV 4:2:0采样,每四个Y共用一组UV分量。

    1、NV12、NV21(属于YUV420)存储方式

    NV12和NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式即Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00。
    YUV420 planar数据, 以720×488大小图象YUV420 planar为例,其存储格式是: 共大小为(720×480×3>>1)字节,分为三个部分:Y,U和V。
    Y分量: (720×480)个字节
    U(Cb)分量:(720×480>>2)个字节
    V(Cr)分量:(720×480>>2)个字节

    三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。
    即YUV数据的0--720×480字节是Y分量值,
    720×480--720×480×5/4字节是U分量,
    720×480×5/4 --720×480×3/2字节是V分量。

    2、4 :2: 2 和4:2:0 转换

    YUV4:2:2 —> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 —> YUV4:2:2 Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。

    3、YUV420sp与YUV420p的数据格式

    它们的UV排列在原理上是完全不同的。
    420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。
    图片来自网络

    • 图片来自网络

    420sp它是UV、UV这样交替存放的。
    图片来自网络

    • 图片来自网络

    有了上面的理论,我就可以准确的计算出一个YUV420在内存中存放的大小。
    width * hight =Y(总和)
    U = Y / 4
    V = Y / 4
    所以YUV420 数据在内存中的长度是 width * hight * 3 / 2。

    4、旋转90度的算法

    public static void rotateYUV24(byte[] src,byte[] des,int width,int height){
    	   int wh = width * height;
    	   //旋转
    	    int k =0;
    	    for(int i =0;i<width;i++){
    		    for(int j=0;j<height;j++){
    			    des[k] = src[width*j + i];
    			    k++;
    		    }
    	    }
    	    for(int i=0;i<width;i+=2){
    		    for(int j=0;j<height/2;j++){
    			    des[k]=src[wh + width*j +i];
    			    des[k+1] = src[wh + width*j + i + 1];
    			    k+=2;
    		    }
        }
    }
    

    5、NV21和NV12

    NV21 颜色空间排列 :YYYYYYYY VUVU
    NV12 颜色空间排列 :YYYYYYYY UVUV
    YUV420SP颜色排列顺序为:YYYYYYY UVUV

    YUV420 是与NV12对应的。

    二、RGB

    R代表Red
    G代表Green
    B代表Blue

    1、RGB565 与RGB888的区别

    RGB565 就是R-5bit,G-6bit,B-5bit
    RGB555 就是R-5bit,G-5bit,B-5bit
    RGB888 就是R-8bit,G-8bit,B-8bit ;其实这就是RGB24

    RGB565 是16位的,2个字节,5+6+5,第一字节的前5位是R,后三位+第二字节前三位是G,第二字节后5位是B。

    RGB555 也是16位的,2个字节,RGB各5位,有1位未用。

    RGB888 是24位的,3个字节。

    三、YUV和RGB的转换公式

    1.小数形式,full range

    R = Y + 1.4075 * (V-128);
    G = Y - 0.3455 * (U-128) - 0.7169*(V-128);
    B = Y + 1.779 * (U-128);

    Y = 0.299R + 0.587G + 0.114B;
    U = (B-Y)/1.772; (U~(-128-127))
    V = (R-Y)/1.402;
    或写为:
    Y = 0.299
    R + 0.587G + 0.114B;
    U = -0.169R - 0.331G + 0.5 B + 128; 注: +128 的含义是让UV的范围处于整数区间(0-255)
    V = 0.5 R - 0.419G - 0.081
    B + 128;

    2.整数形式(减少计算量)full range

    R= Y + ((360 * (V - 128))>>8) ;
    G= Y - (( ( 88 * (U - 128) + 184 * (V - 128)) )>>8) ;
    B= Y +((455 * (U - 128))>>8) ;
    Y = (77R + 150G + 29B)>>8;
    U = ((131
    R - 110G - 21B)>>8) + 128 ;
    V = ((-44R - 87G - 131*B)>>8) + 128;

    3. 量化后的公式( Y~(16,235) U/V ~(16,240) ) tv range

    yuv --> rgb
    R = 1.155Y + 1.605 * V - 224
    G = 1.168
    Y - 0.393 * U - 0.823 * V+ 135.7
    B = 1.168Y + 2.028 * U- 277.8
    rgb --> yuv
    Y= ( 66
    R + 128G + 25B)>>8 + 16
    U= (112R - 94G - 18B)>>8 + 128
    V= (-38
    R - 74G + 112B)>>8 +128

    四、图片尺寸

    1、720P、1080P、2K、4K的区别

    目前主流清晰度主要分为720P(高清)、1080i 、1080P(全高清)、2K、4K。

    1、720P分辨率为1280*720,长宽比16:9,P是Progressive逐行扫描的的意思。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。视频网站这种分辨率的比较多,兼顾了清晰度和画质。

    2、1080i分辨率是1920*1080,长宽比16:9,i是interlace,代表隔行扫描。这种清晰度的视频格式比较少见。

    1080P分辨率是1920*1080,长宽比16:9,P是Progressive逐行扫描的的意思.这也是目前主流的全高清格式。

    3、4K分辨率38402160;是全高清(FHD.19201080)的4倍;高清(HD.1280*720)的9倍。

    2、根据分辨率计算图片的大小

    x bit=2的x次方
    1byte=8bit
    1K=1024byte
    1M=1024K

    看图片格式,如果是图片无损格式,这样计算:

    灰度分辨率小于8Bit黑白:水平像素垂直像素1byte
    灰度分辨率大于8Bit黑白:水平像素垂直像素2byte

    彩色就复杂点,一个像素存储了红绿蓝三色的信息,通场灰度级别为8bit,计算方式为:水平像素垂直像素3byte

    例如: 256x256的图片
    如果是8bit黑白 256x256x1byte=65536 byte=64Kb
    如果是24bit彩色 256x256x3byte=192Kb

    展开全文
  • HTML图像——标记和Src属性 ...Src代表“源”。src属性值是你想要显示图像URL。 语法定义一个形象: URL指向图像存储位置。一幅名为“船。gif”,位于“图像”目录“www.w3schools.com”URL:http://www.
    HTML的图像——< img >标记和Src属性
    在HTML中,图像与< img >标记定义。
    < img >标记是空的,也就是说,它只包含属性,并且没有闭合标签。
    在页面上显示一个图像,你需要使用src属性。Src代表“源”。src属性的值是你想要显示的图像的URL。

    语法定义一个形象:

    <img src="url" alt="some_text"/>

    URL指向图像存储的位置。一幅名为“船。gif”,位于“图像”目录“www.w3schools.com”的URL:http://www.w3schools.com/images/boat.gif。
    浏览器显示的图像出现在标签文档。如果你把一个图像标记两个段落之间,浏览器显示了第一段,然后图像,然后第二段。
    HTML图像Alt属性
    所需的alt属性指定一个替代文本的图片,如果图片不能显示。
    alt属性的值是一个author-defined文本:

    <img src="boat.gif" alt="Big Boat" />

    图像的alt属性提供了替代的信息如果用户因为某种原因不能把它(因为连接缓慢,一个错误在src属性,或者如果用户使用屏幕阅读器)。
    HTML的图像——图像的高度和宽度
    高度和宽度属性用于指定一个图像的高度和宽度。
    默认属性值中指定像素:

    <img src="pulpit.jpg" alt="Pulpit rock" width="304" height="228" />

    提示:这是一个很好的练习来指定一个图像的高度和宽度属性。如果这些属性集,所需的空间图像保留在页面加载的时候。然而,如果没有这些属性,浏览器不知道图像的大小。页面布局的效果将会改变在加载(虽然图片加载)。
    基本的笔记——有用的技巧
    注意:如果一个HTML文件包含十图像- 11个文件必须正确显示页面。加载图片需要时间,因此我最好的建议是:小心使用图片。
    注意:当加载一个网页,浏览器,在那一刻,实际得到的图像从一个web服务器,并将其插入到页面。因此,确保图像实际上在同一地点与web页面,否则你的访客将失效链接图标。失效链接图标显示如果浏览器无法找到图像中。
    展开全文
  • l Web上支持的图片格式 GIF(图形交换格式):GIF格式文件最多只能保存256种颜色,该格式支持透明色,支持动画效果。 JPEG(联合图像专家组):该格式不支持透明色和动画,颜色可达1670万种。 PNG(网络可移植式):该...

    图片

    l  Web上支持的图片格式

    GIF(图形交换格式):GIF格式文件最多只能保存256种颜色,该格式支持透明色,支持动画效果。

    JPEG(联合图像专家组):该格式不支持透明色和动画,颜色可达1670万种。

    PNG(网络可移植式):该格式支持透明色和动画,颜色从几种到1670万种。

    l  图片标记<img src=”图片的路径”/>

      路径:../代表出(向上一级)一层文件夹,/用于分隔文件与文件夹的层次。

    <img />标记的属性和属性值及其说明

    属性名称

    属性值

    说明

    src

    URL

    图片的路径

    alt

    文本

    规定图片的替代文本【图片无法显示时】

    title

    文本

    鼠标悬停时显示的内容

    width

    像素/百分比

    设置图片的宽

    height

    像素/百分比

    设置图片的高

    border

    数字

    设置图像的边框

    align

    left

    图片靠左,文字靠右

    right

    图片靠右,文字靠左

    top

    文字垂直居中上靠

    middle

    文字垂直居中

    botttom

    文字垂直居下(默认)

    vspace

    像素

    定义图像顶部和底部的空白(垂直边距)

    hspace

    像素

    定义图像左侧和右侧的空白(水平边距)

    展开全文
  • 一幅静态图片,你可以说这副图片的fps是0帧/秒,但绝对不能说此时屏幕刷新率是0Hz,也就是说刷新率不随图像内容变化而变化。游戏也好浏览器也好,我们谈到掉帧,是指GPU渲染画面频率降低。比如跌落到30fps甚至20...

    问题1:60Hz和60fps有什么关系?

    没有任何关系。fps代表GPU渲染画面的频率,Hz代表显示器刷新屏幕的频率。一幅静态图片,你可以说这副图片的fps是0帧/秒,但绝对不能说此时屏幕的刷新率是0Hz,也就是说刷新率不随图像内容的变化而变化。游戏也好浏览器也好,我们谈到掉帧,是指GPU渲染画面频率降低。比如跌落到30fps甚至20fps,但因为视觉暂留原理,我们看到的画面仍然是运动和连贯的。(一般60fps已经很流畅了,高于100对于人眼来说是没有任何区别的,这个FPS和显卡,内存,CPU,网络,硬盘有关

    实际情况会比以上想象的复杂的多。即使你能给出一个固定的延时,解决60Hz屏幕下丢帧问题,那么其他刷新频率的显示器应该怎么办,要知道不同设备、甚至相同设备在不同电池状态下的屏幕刷新率都不尽相同。
    以上同时还忽略了屏幕刷新画面的时间成本。问题产生于GPU渲染画面的频率和屏幕刷新频率的不一致:如果GPU渲染出一帧画面的时间比显示器刷新一张画面的时间要短(更快),那么当显示器还没有刷新完一张图片时,GPU渲染出的另一张图片已经送达并覆盖了前一张,导致屏幕上画面的撕裂,也就是是上半部分是前一张图片,下半部分是后一张图片:

    Javascript高性能动画与页面渲染这个文章的图中,例如在14ms的时候,那么只有所有的帧数加起来时间超过16.7ms,那么肯定会丢帧,而每一帧延时这时候是2.7ms,因此16.7/2.7=6也就是在第六帧的时候肯定会丢帧!!如果更新频率为16ms,那么每一帧延迟为0.7ms,那么在16.7/0.7=23.85也就是在24帧的时候肯定会掉帧!!!而且如果动画setInterval的时间间隔越小,那么掉帧的数量会越多!

    PC游戏中解决这个问题的方法是开启垂直同步(v-sync),也就是让GPU妥协,GPU渲染图片必须在屏幕两次刷新之间,且必须等待屏幕发出的垂直同步信号。但这样同样也是要付出代价的:降低了GPU的输出频率,也就降低了画面的帧数。以至于你在玩需要高帧数运行的游戏时(比如竞速、第一人称射击)感觉到“顿卡”,因为掉帧。(丢帧导致的问题就是卡顿,因为在运行其他的任务去了)

    但如果你的回调函数耗时真的很严重,rAF还是可以为你做一些什么的。比如当它发现无法维持60fps的频率时,它会把频率降低到30fps,至少能够保持帧数的稳定,保持动画的连贯。

    问题2:UI引擎和JS引擎是如何互斥的?

    function jank(second) {
        var start = +new Date();
        while (start + second * 1000 > (+new Date())) {}
    }
    div.style.backgroundColor = "red";
    // some long run task
    //UI引擎和JS引擎互斥,先调用UI引擎,然后JS引擎,最后又是UI引擎
    jank(5);
    div.style.backgroundColor = "blue";
    无论在任何的浏览器中运行上面的代码,你都不会看到div变为红色,页面通常会在假死5秒,然后容器变为蓝色。这是因为浏览器的始终只有一个线程在运行(可以这么理解,因为js引擎与UI引擎互斥,浏览器不会马上更新UI,而是会采用队列化修改批量更新的方式来完成的,除非是特殊的属性如innerWidth等,否则肯定会先执行后面的JS代码的)。虽然你告诉浏览器此时div背景颜色应该为红色,但是它此时还在执行脚本,无法调用UI线程。
    var div = document.getElementById("foo");
    var currentWidth = div.innerWidth; 
    div.style.backgroundColor = "blue";
    //这里的UI也不会马上更新,而是会等到后面的JS运行结束后才会执行的
    // do some "long running" task, like sorting data
    我们可以用下面的代码进行优化:

    requestAnimationFrame(function(){
        var el = document.getElementById("foo");
        var currentWidth = el.innerWidth;
        el.style.backgroundColor = "blue";
    });
    // do some "long running" task, like sorting data
    更新背景颜色的代码过于提前,根据前一个例子,我们知道,即使在这里告知了浏览器我需要更新背景颜色,浏览器至少也要等到js运行完毕才能调用UI线程;(延迟这部分的代码)假设后面部分的long runing代码会启动一些异步代码,比如setTimeout或者Ajax请求又或者web-worker,那应该尽早为妙(让后续代码马上执行)。
    问题3:window.onscroll的弊端有哪些

    像scroll,resize这一类的事件会非常频繁的触发,如果把太多的代码放进这一类的回调函数中,会延迟页面的滚动,甚至造成无法响应。所以应该把这一类代码分离出来,放在一个timer中,有间隔的去检查是否滚动,再做适当的处理。原理其实是一样的,为了优化性能、为了防止浏览器假死,将需要长时间运行的代码分解为小段执行,能够使浏览器有时间响应其他的请求。

    var didScroll = false;
    $(window).scroll(function() {
        didScroll = true;
    });
    setInterval(function() {
        if ( didScroll ) {
            didScroll = false;
            // Check your page position and then
            // Load in more results
        }
    }, 250)
    我们也可以采用requestAnimationFrame的方式完成处理:

    var latestKnownScrollY = 0;
    function onScroll() {
        latestKnownScrollY = window.scrollY;
    }
    function update() {
        requestAnimationFrame(update);
        var currentScrollY = latestKnownScrollY;
        // read offset of DOM elements
        // and compare to the currentScrollY value
        // then apply some CSS classes
        // to the visible items
    }
    // kick off
    requestAnimationFrame(update);
    
    这种方式不管我们的latestKnownScrollY是否发生变化,也就是是否发生滚动,那么我们都会不停的执行update方法,这显然是不需要的,例如用户在一个页面一直停留了半个小时而没有发生滚动,这时候的计算是没有必要的。

    var latestKnownScrollY = 0,
        ticking = false;
    //每次滚动的时候都会计算当前滚动的距离,同时也会采用requestAnimationFrame来更新下一帧的内容!
    function onScroll() {
        latestKnownScrollY = window.scrollY;
        requestTick();
    } 
    function requestTick() {
        if(!ticking) {
            requestAnimationFrame(update);
            //如果<下一帧执行完成后>这时候又可以继续监听滚动事件了,而不是像上面的例子每一次不管滚动
            //因此,即使你已经滚动的某个元素,但是因为这时候update没有执行,也就是上一帧还没有执行,因此不会继续往里面添加回调函数的,但是滚动的最新距离是可以获取到的
        }
        ticking = true;
    }
    function update() {
        // reset the tick so we can
        // capture the next onScroll
        ticking = false;
        var currentScrollY = latestKnownScrollY;
        // read offset of DOM elements
        // and compare to the currentScrollY value
        // then apply some CSS classes
        // to the visible items
    }
    window.addEventListener('scroll', onScroll, false);
    注意:在这里不断的滚动是不会插入多个upate方法的,因为ticking为true了,所以只有等到下一帧执行了这个update方法才能继续插入upate,但是我们要注意,这时候页面的垂直滚动距离是不断变化的!
    问题4:我们如何把一个函数推迟到下下帧来执行

    (function(h5){
    	if (!h5) throw new Error("animationFrame.h5ive: core.h5ive required.");
    	var rAF = (window.requestAnimationFrame || window.msRequestAnimationFrame ||
    			window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
    			window.oRequestAnimationFrame),
    		cAF = (window.cancelAnimationFrame ||
    			window.msCancelAnimationFrame || window.msCancelRequestAnimationFrame ||
    			window.mozCancelAnimationFrame || window.mozCancelRequestAnimationFrame ||
    			window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame ||
    			window.oCancelAnimationFrame || window.oCancelRequestAnimationFrame),
    		publicAPI, q_ids = {}
    	;
         //产生一个独一无二的ID值
    	function qID(){
    		var id;
    		do {
    			id = Math.floor(Math.random() * 1E9);
    		} while (id in q_ids);
    		return id;
    	}
    	//插入下一帧,返回的是这个独一无二的数字
    	function queue(cb) {
    		var qid = qID();
    		//通过这个独一无二的ID来向回调函数中放置回调函数。q_ids[111111113334]=12,q_ids[456789098]=24。调用返回的一个唯一的整数值(浏览器来返回的),通过这个整数值就能够取消这一次的调用!!!
    		q_ids[qid] = rAF(function(){
    			delete q_ids[qid];
    			cb.apply(publicAPI,arguments);
    			//这个元素的回调函数中的参数是除了回调函数以外给queue传入的参数
    		});
    		return qid;
    	}
       //插入下下一帧,queue的作用是把函数放在下一帧中去执行,不过这个qid是全局唯一的!
    	function queueAfter(cb) {
    		var qid;
    		qid = queue(function(){
    			// do our own rAF call here because we want to re-use the same `qid` for both frames
    			q_ids[qid] = rAF(function(){
    				delete q_ids[qid];
    				cb.apply(publicAPI,arguments);
    			});
    		});
    		return qid;
    	}
    	//取消某一个回调
    	function cancel(qID) {
    		if (qID in q_ids) {
    			cAF(q_ids[qID]);
    			delete q_ids[qID];
    		}
    		return publicAPI;
    	}
    	function unsupported() {
    		throw new Error("'requestAnimationFrame' not supported.");
    	}
         //如果支持RAF那么就走这里的逻辑
    	if (rAF && cAF) {
    		publicAPI = {
    			queue: queue,
    			queueAfter: queueAfter,
    			cancel: cancel
    		};
    	}
    	else {
    		publicAPI = {
    			queue: unsupported,
    			queueAfter: unsupported,
    			cancel: unsupported
    		};
    	}
    	h5.animationFrame = publicAPI;
    
    })(this.h5);
    
    因为每一个rAF函数都会返回一个独一无二的整数,而且这个整数是由浏览器决定的。通过这个整数我们可以取消某一个调用。

                 function queue(cb) {
    		var qid = qID();
    		//通过这个独一无二的ID来向回调函数中放置回调函数。q_ids[111111113334]=12,q_ids[456789098]=24。调用返回的一个唯一的整数值(浏览器来返回的),通过这个整数值就能够取消这一次的调用!!!
    		q_ids[qid] = rAF(function(){
    			delete q_ids[qid];
    			cb.apply(publicAPI,arguments);
    			//这个元素的回调函数中的参数是除了回调函数以外给queue传入的参数
    		});
    		return qid;
    	}

    这个函数是把函数推迟到下一帧执行,而且每次都会产生一个独一无二的qid值作为数组的键,而值是rAF函数返回的一个唯一的值。当下一帧这个函数执行后那么我们就会从这个数组中清除相应的键和值,但是这里采用的delete删除,因此会留下undefined!

    问题5:低版本的浏览器中没有requestAnimationFrame如何用setTImeout进行兼容

     function rAFShim(){
       var timeLast = 0;
      	 //表示上一次动画开始执行的时间(更新时候由当前时间和时间偏移量组成)
        return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
            var timeCurrent = (new Date()).getTime(),
             //回调函数执行的时间
                timeDelta;
            timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));//如果timeCurrent和timelast之间超过了16ms,那么表示延迟了,立即执行就可以
            timeLast = timeCurrent + timeDelta;//timeLast的值更新需要计算,也就是在当前时间的基础性加上延迟或者提前的时间
            //callback会传入一个时间值,(该时间值为由浏览器传入的从1970年1月1日到当前所经过的毫秒数)
            return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
        };
     };
    如下面就是通过这个函数实现的简单的动画展开效果:

     function rAFShim(){
       var timeLast = 0;
        return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
            var timeCurrent = (new Date()).getTime(),
                timeDelta;
            timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));//由于其他代码的执行对于动画产生的延迟影响
            timeLast = timeCurrent + timeDelta;
            return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
        };
     };
     //实现展开效果函数
      function width_changing(){
       if(nowContainer<=411){
           container.style.width=nowContainer/128+"rem";
           nowContainer+=15;//简单的变化
           ticker(width_changing);
        }
      }
     var ticker = window.requestAnimationFrame || rAFShim();
      ticker(width_changing);//启动动画
    1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

    2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。注意:上面这个函数是不兼容ipad/iphone/ipod,可以看如下的兼容函数:

    if (!Date.now)
        Date.now = function() { return new Date().getTime(); };
    
    (function() {
        'use strict';
        var vendors = ['webkit', 'moz'];
        for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {//如果webkit存在了,那么这里的判断条件不在满足不会循环了
            var vp = vendors[i];
            window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
            window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
                                       || window[vp+'CancelRequestAnimationFrame']);
        }
        if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy,兼容ios6的
            || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
            var lastTime = 0;
            window.requestAnimationFrame = function(callback) {
                var now = Date.now();
                var nextTime = Math.max(lastTime + 16, now);//lastTime+16表示预期执行的时刻,而now表示实际执行的时刻,如果实际时刻提前了会延迟
                return setTimeout(function() { callback(lastTime = nextTime); },
              //如果延迟了那么执行时刻就是now,如果提前了执行时刻lastTime+16,因为提前了我还会延迟函数的执行时间nextTime-now秒
                                  nextTime - now);//nextTime-now>=0,如果大于0表示lastTime+16>now,也就是实际执行的时间提前了,于是延迟就可以了
            };
            window.cancelAnimationFrame = clearTimeout;
        }
    }());

    参考文献:

    深入理解requestAnimationFrame

    深入探究使JavaScript动画流畅的一些方法

    性能更好的js动画实现方式——requestAnimationFrame

    兼容性的raf解决方案

    展开全文
  • 阅读本文前,请您先点击上面“蓝色字体”...注:本文转载自网络,不代表本平台立场,仅供读者参考,著作权属归原创者所有。我们分享此文出于传播更多资讯之目的。如有侵权,请在后台留言联系我们进行删除,谢谢! ...
  • 硬盘基本知识

    2017-02-07 18:09:00
    凸起地方代表数字1(磁化为1),凹地方代表数字0。因此硬盘可以以二进制来存储表示文字、图片等信息。 1. 硬盘组成 一般说来,机械硬盘,都是由盘片、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、...
  • JAVA集合的知识点复习

    2018-09-20 21:14:10
    图片出自黑马程序员JAVA教程中的图片,供参考,感谢毕向东老师。。。。。 图中虚线代表着接口,实线代表着类。 Map: 一次添加一堆元素,Collection 一次添加一个元素 Map也称为双列集合,Collectio...
  • java基础知识总结ppt

    千次阅读 2016-03-21 17:08:35
    昨天加上今天,我把java基础知识总结的ppt做好了,其中包括: ...而且我也截了几张项目的图片在ppt上,增加了ppt的观赏性。 Java入门:五子棋 Java应用程序界面编程、添加按钮、下棋的算法和容器设计、按钮功能
  • 基础篇说说你对MVVM理解Model-View-ViewModel缩写,Model代表数据模型,View代表UI组件,ViewModel将Model和View关联起来数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化时候会通知viewModel层更新...
  • 爆破crc校验所需要了解到PNG文件头知识- (固定)八个字节89 50 4E 47 0D 0A 1A 0A为png文件头- (固定)四个字节00 00 00 0D(即为十进制13)代表数据块长度为13- (固定)四个字节49 48 44 52(即为ASCI...
  • crc 是循环冗余检验 (固定)八个字节89 50 4E 47 0D 0A 1A 0A为png文件头 ...前四个字节代表图片的宽 后四个字节代表图片的高 后五个字节依次为: Bit depth、ColorType、 Compression method、 Filter meth
  • java去除图片水印解决办法

    千次阅读 2018-06-28 10:54:35
    长300宽400像素的图片所有像素为300×400=120000个像素点。在ARGB的图像表示方法中,每个像素点有ARGB四个通道, A代表透明度,取值范围0~255, R代表三原色中的红,取值范围0~255, G代表...
  • 相对路径./代表当前路径,../代表上一级路径 ctrl键+/键组合键,是显示和不显示代码切换键 行内元素 a标签(点击后,会链接到另外一个页面) img标签(显示一个图片) input标签(显示一个输入框) button...
  • 1.布局的背景可以引入一个layout-list.xml代表设置变换的图片,布局上面 中间 结束的颜色不同 1 <?xml version="1.0" encoding="utf-8"?> 2 <layer-list 3 xmlns:android=...
  • 知识图谱【一】理论

    2021-01-21 23:35:59
    基于知识图片的问答 知识图谱介绍 什么是知识图谱 知识图谱,是通过将应用数学、图形学、信息可视化技术、信息科学等学科理论与方法与计量学引文分析、共现分析等方法结合,并利用可视化图谱形象地展示学科...
  • ![图片说明]...想要实现一个这样动态仪表盘,最长那个一根代表指针,没有找到合适插件,请问怎么才能实现 如果有代码就更好了,没有话能告诉我需要用到哪些知识嘛,谢谢!
  • 本文介绍了html5中将图片的绝对路径转换成文件对象,分享给大家,具体如下...代表用户选择所有文件。我们先来看一个简单demo,看下file文件对象有哪些属性。如下代码: <!DOCTYPE html> <html> <hea
  • 这次我们来讨论例如美图秀秀中对一张图片改变图片风格操作。很多女孩子自拍后往往会对照片进行美化。我们来说说这个问题。 1.首先我们应该了解一个知识点: 图像颜色处理主要借助颜色矩阵(ColorMatrix)这...
  • GAN基础知识

    2020-07-08 13:07:39
    GAN主要灵感来源于博弈论中零和博弈思想,应用到深度学习神经网络上来说,就是通过生成网络G(Generator)和判别网络D(Discriminator)不断...它输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率
  • 那么对于一张图片而言,卷积操作是如何进行呢? 什么是卷积核? 一张图片进行卷积后显示效果,绝大部分取决于它卷积核(kernel)。...它里面元素值代表不同权值。一般而言,卷积核里面所有元素...
  • iOS中的图片使用方式、内存对比和最佳实践 预备知识 我们的对比主要关注内存的占用情况。对比的格式是jpg和png这两种最广泛使用的格式,分别代表了有损压缩和无损压缩;关于它们的特点和介绍,可以参考郭耀源的这篇...
  • 最近在看字符编码的相关知识,又联想到二进制代码的知识,由于本人不是科班出身,对一些二进制代码即本地代码了解不深,所以有几个问题感到很困惑,所以希望懂相关知识的人帮我顺一顺。 VS默认是将文本本件(包括cs...
  • 在介绍图片格式之前首先普及一下图片的基本知识: 彩色图像:每个像素由R、G、B三个分量表示,每个通道取值范围0~255。数据类型一般为8位无符号整形。 灰度图像:每个像素只有一个采样颜色图像,这类图像通常显示...
  • 什么是CC0协议CC0是CC协议(“知识共享”是Creative Commons在中国大陆...采用该协议即代表作者宣布放弃该创作一切版权,该创作进入共有领域(公有领域是指任何个人或团体都不具有其所有权的知识财产。版权到期...
  • knowledge:代表知识模块(可以理解为书本中单元标题) knowledge_point:代表知识点模块(单元中小知识点,其中""分割每个小知识) folderpath:存放知识点文件夹 txtname:知识点名称(“”下划线作用同上) ...
  • img = cv2.imread(annotation_data['filepath']) #opencv的知识,读取图片,参数:图片的路径文件名 for bbox in annotation_data['bboxes']: cv2.rectangle(img, (bbox['x1'], bbox['y1']), (bbox[ #代表在img这个...
  • 很多程序员都有这样觉悟;...因为在工作之前,学历在很大程度上就已经代表了你能力 一、图片 1、图片库对比 2、LRUCache原理 3、图片加载原理 4、自己去实现图片库,怎么做? 5、Glide源码解析 6、Glide
  • Python OCR识别图片验证码(二)

    千次阅读 2017-05-31 11:51:17
    Python:3.5上节讲到验证码的简单识别但对于一些复杂的验证码,我们需要做一些简单的图片处理才能识别。例如,我要识别这些验证码: 设计思路:首先将图片变灰,然后转为RGBA,即四个通道,每个通道代表每种颜色,...
  • Bitmap基础知识

    2018-04-27 15:38:13
    (一)Bitmap所占用内存 = 图片长度 x 图片宽度 x 一个像素点占用字节数A代表透明度;R代表红色;G代表绿色;B代表蓝色ALPHA_8 表示8位 Alpha位图,即A=8,一个像素点占用一个字节,它没有颜色,只有透明度ARGB...
  • Android缩放图片和旋转图片示例

    千次阅读 2012-12-05 19:35:15
    得到位图Bitmap的方式我总结了四种方式,不管哪种方式得到的图片相关的位图, 都可以用ImageView对象的setImageBitmap(Bitmap bitmap)函数,把与位图相关的图片设置在ImageView中显示出来 (1)从sdcard中图片路径去...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 398
精华内容 159
关键字:

代表知识的图片