emcc编译选项

source: https://emscripten.org/docs/compiling/Building-Projects.html

To see a list of all available ports
emcc
 –show-ports

一、使用SDL_image

参考【1】用这个可以获得image宽、高,返回image data
Gets preloaded image data and the size of the image.

二、使用SDL_net
SDL_net has also been added to ports, use it with

三、编译优化
In order to properly optimize code, it is usually best to use the same optimization flags and other compiler options when compiling source to object code, and object code to JavaScript (or HTML).

 

参考:
1. emscripten.h
https://emscripten.org/docs/api_reference/emscripten.h.html#c.emscripten_get_preloaded_image_data

wasm

emcc client.c -s USE_SDL=2 -s USE_SDL_NET=2 -s USE_SDL_IMAGE=2 -s WASM=1 -o sdl2.html

 

client.c:
—————————–
#include “SDL.h”
#include “SDL_net.h”
#include <emscripten/emscripten.h>
int EMSCRIPTEN_KEEPALIVE linkToServer(int port)
{

}

How to reduce rpm size using rpmbuild

编译出来的rpm就是比deb大,就去研究如何减少rpm的大小
关键还是在SPECS文件上,要改变默认的压缩方式,在%prep后面加上这句就行了:
%define _binary_payload w7.xzdio
# Compression type and level for source/binary package payloads.
# “w9.gzdio”: gzip level 9 (default).
# “w9.bzdio”: bzip2 level 9.
# “w7.xzdio”: xz level 7, xz’s default.
# “w7.lzdio”: lzma-alone level 7, lzma’s default

 

参考:
https://stackoverflow.com/questions/9292243/rpmbuild-change-compression-format

[win10 linux subsystem] dpkg-deb error: control directory has bad permissions 777 (must be >=0755 and <=0775)

打算用win10 linux 子系统来打包ubuntu使用的deb安装包,结果运行dpkg-deb报错:
control directory has bad permissions 777 (must be >=0755 and <=0775)

解决方案:
sudo umount /mnt/e
sudo mount -t drvfs -o uid=1000,gid=1000,umask=022 e: /mnt/e

就是说要重新mount一下,mount的时候就决定了目录权限

[2019-07-06 updated]
按照http://zuyunfei.com/2018/06/15/file-system-configuration-in-wsl/的方法,
在C:\Users\%CurrentUser%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc\LocalState\rootfs\etc上建立一个文件,名字叫wsl.conf,内容如下:
[automount]
enabled = true
root = /mnt/
options = “uid=1000,gid=1000,metadata,umask=022”
mountFsTab = false

进入任一目录,打开linux shell,再mount看一下,完美~

 

参考:
https://www.askingbox.com/question/error-message-dpkg-deb-error-control-directory-has-bad-permissions-777
https://www.askingbox.com/question/linux-get-own-user-id-uid-gid
http://zuyunfei.com/2018/06/15/file-system-configuration-in-wsl/

 

测试MQ算术编码

JBig2_fcd14492.pdf
H.2 Test sequence for arithmetic coder
The source data:
0x00, 0x02, 0x00, 0x51, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x52, 0x87, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA,
0x82, 0xC0, 0x20, 0x00, 0xFC, 0xD7, 0x9E, 0xF6, 0xBF, 0x7F, 0xED, 0x90, 0x4F, 0x46, 0xA3, 0xBF

The encoded data:
0x84, 0xC7, 0x3B, 0xFC, 0xE1, 0xA1, 0x43, 0x04, 0x02, 0x20, 0x00, 0x00, 0x41, 0x0D, 0xBB, 0x86,
0xF4, 0x31, 0x7F, 0xFF, 0x88, 0xFF, 0x37, 0x47, 0x1A, 0xDB, 0x6A, 0xDF, 0xFF, 0xAC

 

MAC下编译动态链接库函数的可见性

编译的时候加上 -fvisibility=hidden,可以隐藏一般函数的可见性,如果要使得函数可见,则要加上__attribute__((visibility(“default”)))

代码如下:

 

保存成a.c,然后用命令行编译:

gcc -shared -fPIC a.c -fvisibility=hidden

此时生成a.out,然后用nm查看,可以看到函数a前面是小t,说明是隐藏的,函数b前面是大T,说明是可见的

数组读取性能比较

1~255的数组,如何组织起来,读取比较快?

1)用BYTE数组
2)用int数组(32位)
3)用long long数组(64位)

 

 

 

结论:64位的最快,但比32位只快了一点点,比BYTE数组快很多(一倍以上)

浅谈document.domain

原文:http://yanni4night.com/2014/04/23/setting-document-domain/

在需要主子域跨域技术的应用场景中,父 frame 和子 frame 设置相同的 document.domain 是一种特别常用的方式,我们可以看见腾讯公司的页面中很多都会有一句:

qq.com 域页面的登录行为很多都是依赖这种方式与iframe结合来实现的。

事实上,W3C 的 DOM 2 HTML标准将 document.domain定义为只读的:

domain of type DOMString, readonly The domain name of the server that served the document, or null if the server cannot be identified by a domain name.

HTML5 草案 中有关于对 document.domain赋值的内容。

在 Webkit 的 Document.idl 源码中对 domain 有这样的定义:

这也说明了 domain 设置为“writable” 仅用于页面脚本:即允许主子域脚本进行通信,但不涉及 localStorageindexedDB 和 XMLHttpRequest 的共享。目前市场上主流浏览器都支持 domain可写,可以满足几乎所有主子域脚本通信需求,但在特殊情况下也有些许不同。

所有浏览器都不支持设置 domain 为当前域子域或不完整的超域,比如当前域为 “abc.google.com” ,那么设置domain 为 “www.abc.google.com” 或”ogle.com” 都是不允许的。现在测试各个浏览器在 host 为以下情形下设置不同domain的反应:

  • 为IP地址
  • 单节域名
  • 多节域名

测试 host 为 “google”、“www.google.com”、“10.11.202.231”。由子域名向父域名测试,因此前面的测试不会对后面的测试造成干扰。

UA/host google www.google.com 10.11.202.231
Firefox(Mac/Windows/Android) s.ff

 

m.ff ip.ff
Safari(iOS/Mac/Windows) s.safari m.safari ip.safari
IE6~7 s.ie67 m.ie67 ip.ie67
Chrome(Mac,Windows)
IE8~10
Opera(presto内核,Mac  / Windows )
s.chrome-ie810-opera m.chrome-ie810-opera ip.chrome-ie810-opera
IE(WP8) 无法打开 m.chrome-ie810-opera ip.chrome-ie810-opera

由上表可得出以下结论:

  • Firefox可以接受带 port 的父域名,但是任意 port 都会被忽略,其它浏览器则会报错;
  • 对于IP地址,IE6、IE7和Safari简单地将其当做为域名;
  • 仅Safari允许将 domain 设置为最后一节域名。Safari 以及 国内几乎所有带 webkit 内核的浏览器 使用了一种相对简单的方式,即在字符串层面上新的domain 是当前 domain 的“父域名”即可,可以从 webkit 中 Document.cpp 文件的源代码中看出:

因此即使是IP地址或是最后一节 domain 也会被允许设置。Internet Explorer 不开源,但可以猜测其对多节域名进行了最后一节域名限制,在 IE8+ 上增加了IP地址限制。Firefox 在3.0版本增加了此限制。对于单节域名如 http://hello/,所有浏览器都一致性地允许设置,当然,这相当于设置 domain 为自身。

Firefox浏览器忽略 port 的行为初衷不得而知,但可以测试该特性是在3.0版本上增加的。

值得一提的是,chromium 项目对 webkit 进行了一些修改,从而带来了一些新的特性,观察 Document.cpp 文件的源代码:

可见除了支持HTML5的 sandbox 之外,还增加了IP地址检测,因此 Chrome 才不会像Safari那样允许IP地址的一段设置为 domain。特别地,Chrome 还进行了顶级域名检测, chromium 项目会生成一个effective_tld_names.gperf 文件,提供了很多域名列表,末尾标记不为0的域名将不能设置为document.domain。比如,一个域名为www.english.uk的页面,在 Chrome 下将不能设置 document.domain为 english.uk,因为 english.uk 被认为是顶级域名从而报错:

SecurityError: Failed to set the ‘domain’ property on ‘Document’: ‘english.uk’ is a top-level domain.

这部分逻辑的一些代码来自 Mozilla ,因此Firefox (3.0+)也具有同样的特性。

截止今天(2014-04-24),这个列表至少包含472个顶级域名,包括孟加拉国、文莱、库克群岛、塞浦路斯、厄立特里亚、埃塞俄比亚、斐济、马尔维纳斯群岛、关岛、以色列、牙买加、肯尼亚、柬埔寨、科威特、缅甸、莫桑比克、尼加拉瓜、尼泊尔、新西兰、巴布亚新几内亚、土耳其、英国、也门、南非、赞比亚、津巴布韦等国家和地区的顶级域名。想必这些国家的网站在设置 document.domain 时会遇到一些困难了:)。

在对IE浏览器进行测试时,也发现了一些奇怪的事情。实验“aa.bb.cc.dd”域名,发现在 IE8+ 下将不能设置document.domain 为“cc.dd”。经过反复测试发现 IE8+在多节域名下允许设置 的双节域名中,两节单词中要至少有一个大于2个字母,换言之,下列域名都是不允许的:

  • sa.cn
  • o.jp
  • x.m

但下列是允许的:

  • sax.cn
  • o.com
  • xxx.k

暂不知微软用意为何,但可以联想到,新浪微博的短域名 t.cn在有下一级域名的情形下,将不能设置document.domain为 t.cn

即便拥有上面的诸多问题,不过都属于特例,除了 IE8+ 的短域名问题,其它基本都不会在日常的开发中遇到。

参考
  1. http://javascript.info/tutorial/same-origin-security-policy
  2. http://msdn.microsoft.com/en-us/library/ie/ms533740(v=vs.85).aspx
  3. https://developer.mozilla.org/en-US/docs/Web/API/document.domain

Object properties in JavaScript

[译]JavaScript中对象的属性

src: http://www.2ality.com/2012/10/javascript-properties.html
中文: http://www.cnblogs.com/ziyunfei/archive/2012/10/30/2745786.html

Update 2013-08-25: Blog post “Protecting objects in JavaScript” (Object.preventExtensions()Object.seal()Object.freeze()).

Properties determine the state of an object in JavaScript. This blog post examines in detail how they work.

Kinds of properties

JavaScript has three different kinds of properties: named data properties, named accessor properties and internal properties.

Named data properties (“properties”)

“Normal” properties of objects map string names to values. For example, the following objectobj has a data property whose name is the string "prop" and whose value is the number 123.

You can get (read) a property:

And you can set (write) a property:

Named accessor properties

Alternatively, getting and setting a property value can be handled via functions. Those functions are called accessor functions. A function that handles getting is called a getter. A function that handles setting is called a setter.

Let’s interact with obj:

Internal properties

Some properties are only used by the specification. They are called “internal”, because they are not directly accessible via the language, but they do influence its behavior. Internal properties have special names that are written in double square brackets. Two examples:

  • The internal property [[Prototype]] points to the prototype of an object. It can be read viaObject.getPrototypeOf(). Its value can only be set by creating a new object that has a given prototype, e.g. via Object.create() or __proto__ [1].
  • The internal property [[Extensible]] determines whether or not one can add properties to an object. It can be read via Object.isExtensible(). It can be set false viaObject.preventExtensions(). Once false, it cannot be become true again.

Property attributes

All of the state of a property, both its data and its meta-data, is stored in attributes. They are fields that a property has, much like an object has properties. Attribute keys are often written in double brackets.

The following attributes are specific to named data properties:

  • [[Value]] hold the property’s value, its data.
  • [[Writable]] holds a boolean indicating whether the value of a property can be changed.

The following attributes are specific to named accessor properties:

  • [[Get]] holds the getter, a function that is called when a property is read. That function computes the result of the read access.
  • [[Set]] holds the setter, a function that is called when a property is set to a value. The function receives that value as a parameter.

All properties have the following attributes:

  • [[Enumerable]] holds a boolean. Making a property non-enumerable hides it from some operations (see below).
  • [[Configurable]] holds a boolean. If false, you cannot delete a property, change any of its attributes (except [[Value]]) or convert between data property and accessor property. In other words, [[Configurable]] controls the writability of a property’s meta-data.

Default values

If you don’t specify attributes, the following defaults are used:

 

Attribute key Default value
[[Value]] undefined
[[Get]] undefined
[[Set]] undefined
[[Writable]] false
[[Enumerable]] false
[[Configurable]] false

These defaults are especially important for property descriptors (see below).

Property descriptors

A property descriptor encodes the attributes of a property as an object. Each of the properties of that object corresponds to an attribute. For example, the following is the descriptor of a read-only property whose value is 123:

You can achieve the same goal, immutability, via accessors. Then the descriptor looks as follows:

Functions that use property descriptors

The following functions allow you to work with property descriptors:

  • Object.defineProperty(obj, propName, propDesc)
    Create or change a property on obj whose name is propName and whose attributes are specified via propDesc. Return the modified object. Example:
  • Object.defineProperties(obj, propDescObj)
    The batch version of Object.defineProperty(). Each property of propDescObj holds a property descriptor. The names of the properties and their values tellObject.defineProperties what properties to create or change on obj. Example:
  • Object.create(proto, propDescObj?)
    First, create an object whose prototype is proto. Then, if the optional parameter propDescObjhas been specified, add properties to it – in the same manner as Object.defineProperties. Finally, return the result. For example, the following code snippet produces the same result as the previous snippet:
  • Object.getOwnPropertyDescriptor(obj, propName)
    Returns the descriptor of the own (non-inherited) property of obj whose name is propName. If there is no such property, undefined is returned.

Enumerability

This section explains which operations are influenced by enumerability and which aren’t. Below, we are assuming that the following definitions have been made:

Note that objects (including proto) normally have at least the prototype Object.prototype [2]:

Object.prototype is where standard methods such as toString and hasOwnProperty are defined.

Operations affected by enumerability

Enumerability only affects two operations: The for-in loop and Object.keys().

The for-in loop iterates over the names of all enumerable properties, including inherited ones (note that none of the non-enumerable properties of Object.prototype show up):

Object.keys() returns the names of all own (non-inherited) enumerable properties:

If you want the names of all own properties, you need to use Object.getOwnPropertyNames()(see example below).

Operations that ignore enumerability

All other operations ignore enumerability. Some read operations take inheritance into consideration:

Other read operations only work with own properties:

Creating, deleting and defining properties only affects the first object in a prototype chain:

Best practices

The general rule is that properties created by the system are non-enumerable, while properties created by users are enumerable:

That especially holds for the methods in prototype objects:

Thus, for your code, you should ignore enumerability. You normally shouldn’t add properties to built-in prototypes and objects, but if you do, you should make them non-enumerable to avoid breaking code.

As we have seen, non-enumerability mostly benefits for-in and ensures that legacy code using it won’t break. The non-enumerable properties create the illusion that for-in only iterates over the user-created own properties of an object. In your code, you should avoid for-in if you can [3].

If you use objects as maps from strings to values, you should only work with own properties and ignore enumerability. But there are more pitfalls for this use case [4].

Conclusion

In this post, we have examined the nature of properties, which is defined via so-called attributes. Note that actual JavaScript implementations do not necessarily organize properties via attributes, they are mainly an abstraction used by the ECMAScript specification. But one that is sometimes visible in the language itself, for example in property descriptors.

Further reading on 2ality:

References

  1. JavaScript: __proto__
  2. What object is not an instance of Object?
  3. Iterating over arrays and objects in JavaScript
  4. The pitfalls of using objects as maps in JavaScript

HTML5 cavas

导航


  • 前言
  • 基本知识
  • 绘制矩形
  • 清除矩形区域
  • 圆弧
  • 路径
  • 绘制线段
  • 绘制贝塞尔曲线
  • 线性变
  • 径向渐变(发散)
  • 图形变形(平移、旋转、缩放)
  • 矩阵变换(图形变形的机制)
  • 图形组合
  • 给图形绘制阴影
  • 绘制图像(图片平铺、裁剪、像素处理[不只图像、包括其他绘制图形])
  • 绘制文字
  • 保存和恢复状态(context)
  • 保存文件
  • 结合setInterval制作动画
  • 结语、demo下载

前言


<canvas></canvas>是html5出现的新标签,像所有的dom对象一样它有自己本身的属性、方法和事件,其中就有绘图的方法,js能够调用它来进行绘图 ,最近在研读《html5与css3权威指南》下面对其中最好玩的canvas的学习做下读书笔记与实验。

温馨提示:以下所有实验请使用最新版的opera

基本知识


    context:一直觉得这个翻译成“上下文”真够蛋疼的,context是一个封装了很多绘图功能的对象,获取这个对象的方法是  

        var context =canvas.getContext(“2d”);

也许这个2d勾起了大家的无限遐想,但是很遗憾的告诉你html5还只是个少女,不提供3d服务。

       canvas元素绘制图像的时候有两种方法,分别是

context.fill()//填充

context.stroke()//绘制边框

style:在进行图形绘制前,要设置好绘图的样式

context.fillStyle//填充的样式

context.strokeStyle//边框样式

context.lineWidth//图形边框宽度

颜色的表示方式:

直接用颜色名称:”red” “green” “blue”

十六进制颜色值: “#EEEEFF”

rgb(1-255,1-255,1-255)

rgba(1-255,1-255,1-255,透明度)

和GDI是如此的相像,所以用过GDI的朋友应该很快就能上手

绘制矩形  context.fillRect(x,y,width,height)  strokeRect(x,y,width,height)


     x:矩形起点横坐标(坐标原点为canvas的左上角,当然确切的来说是原始原点,后面写到变形的时候你就懂了,现在暂时不用关系)

     y:矩形起点纵坐标

     width:矩形长度

     height:矩形高度

清除矩形区域 context.clearRect(x,y,width,height)


     x:清除矩形起点横坐标

     y:清除矩形起点纵坐标

     width:清除矩形长度

     height:清除矩形高度

 圆弧context.arc(x, y, radius, starAngle,endAngle, anticlockwise)


    x:圆心的x坐标

    y:圆心的y坐标

    straAngle:开始角度

    endAngle:结束角度

    anticlockwise:是否逆时针(true)为逆时针,(false)为顺时针

ps:经过试验证明书本上ture是顺时针,false是逆时针是错误的,而且无论是逆时针还是顺时针,角度都沿着顺时针扩大,如下图:

 

一不小心画了小日本的国旗…赶紧调下颜色和大小,绿色倒是挺合适的~

路径  context.beginPath()    context.closePath()


细心的朋友会发现上面的画圆并不单单是直接用arc还用到了context的 beginPath   和closePath方法,参考书不愧是参考书,例子给得太简单了,实话说一开始我凌乱了,耐心下来做了几个实验才舒缓蛋疼的心情

实验代码如下,通过分别注释closePath 和beginPath看fill stoke 和fill stroke结合下画出来的两个1/4弧线达到实验效果

实验结果如下:

得出的结论有:*号为重点

1、系统默认在绘制第一个路径的开始点为beginPath

*2、如果画完前面的路径没有重新指定beginPath,那么画第其他路径的时候会将前面最近指定的beginPath后的全部路径重新绘制

3、每次调用context.fill()的时候会自动把当次绘制的路径的开始点和结束点相连,接着填充封闭的部分

ps:书本的结论是   如果没有closePath那么前面的路劲会保留,实验证明正确的结论是 如果没有重新beginPath那么前面的路劲会保留

ps1:如果你真心凌乱了,那么记住每次画路径都在前后加context.beginPath()   和context.closePath()就行

 绘制线段 context.moveTo(x,y)  context.lineTo(x,y)


    x:x坐标

    y:y坐标

每次画线都从moveTo的点到lineTo的点,

如果没有moveTo那么第一次lineTo的效果和moveTo一样,

每次lineTo后如果没有moveTo,那么下次lineTo的开始点为前一次lineTo的结束点

下面给出书本的例子,一朵绿色的菊花,涉及数学,不多解析,有兴趣的自己研究

绘制贝塞尔曲线(贝济埃、bezier) context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 

绘制二次样条曲线 context.quadraticCurveTo(qcpx,qcpy,qx,qy)


    cp1x:第一个控制点x坐标

    cp1y:第一个控制点y坐标

    cp2x:第二个控制点x坐标

    cp2y:第二个控制点y坐标

    x:终点x坐标

    y:终点y坐标

     qcpx:二次样条曲线控制点x坐标

    qcpy:二次样条曲线控制点y坐标

    qx:二次样条曲线终点x坐标

    qy:二次样条曲线终点y坐标

下面给出书本的例子,一朵扭曲的绿色菊花…编书这哥们对菊花情有独钟啊- –

 线性渐变 var lg= context.createLinearGradient(xStart,yStart,xEnd,yEnd)

 线性渐变颜色lg.addColorStop(offset,color)


    xstart:渐变开始点x坐标

    ystart:渐变开始点y坐标

    xEnd:渐变结束点x坐标

    yEnd:渐变结束点y坐标

     offset:设定的颜色离渐变结束点的偏移量(0~1)

    color:绘制时要使用的颜色

给出书本偏移量的解析图,从图可以看出线性渐变可以是两种以上颜色的渐变

径向渐变(发散)var rg=context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd)

径向渐变(发散)颜色rg.addColorStop(offset,color)


    xStart:发散开始圆心x坐标

    yStart:发散开始圆心y坐标

    radiusStart:发散开始圆的半径

    xEnd:发散结束圆心的x坐标

    yEnd:发散结束圆心的y坐标

    radiusEnd:发散结束圆的半径

     offset:设定的颜色离渐变结束点的偏移量(0~1)

    color:绘制时要使用的颜色

书本并没有给出发散偏移量的图,特地画了幅:

下面给出两个实验

图形变形


1、平移context.translate(x,y)

    x:坐标原点向x轴方向平移x

    y:坐标原点向y轴方向平移y

2、缩放context.scale(x,y)

    x:x坐标轴按x比例缩放

    y:y坐标轴按y比例缩放

3、旋转context.rotate(angle)

    angle:坐标轴旋转x角度(角度变化模型和画圆的模型一样)

由于(平移,缩放,旋转)和(平移,旋转,缩放)一样

(缩放,选装,平移)和(旋转,缩放,平移)一样

所以实验结果只能看到“4”中情况,其实是有两种情况被覆盖了

下面给出平移,缩放,旋转先后顺序不同,坐标轴的变化图

矩阵变换 context.transform(m11,m12,m21,m22,dx,dy)


所谓的矩阵变换其实是context内实现平移,缩放,旋转的一种机制

他的主要原理就是矩阵相乘

额,要讲解这个可以另开一个篇幅,庆幸的是已经有人做了总结,可以参考下面这篇文章

http://hi.baidu.com/100912bb_bb/item/90c4a7489518b0fa1281daf1

我们需要了解的是

context.translate(x,y) 等同于context.transform (1,0,0,1,x,y)或context.transform(0,1,1,0.x,y)

context.scale(x,y)等同于context.transform(x,0,0,y,0,0)或context.transform (0,y,x,0, 0,0);

context.rotate(θ)等同于

context.transform(Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180),

-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),0,0)

context.transform(-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),

Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180), 0,0)

 图形组合 context.globalCompositeOperation=type


    图形组合就是两个图形相互叠加了图形的表现形式,是后画的覆盖掉先画的呢,还是相互重叠的部分不显示等等,至于怎么显示就取决于type的值了
    type:

        source-over(默认值):在原有图形上绘制新图形

        destination-over:在原有图形下绘制新图形

        source-in:显示原有图形和新图形的交集,新图形在上,所以颜色为新图形的颜色

        destination-in:显示原有图形和新图形的交集,原有图形在上,所以颜色为原有图形的颜色

        source-out:只显示新图形非交集部分

        destination-out:只显示原有图形非交集部分

        source-atop:显示原有图形和交集部分,新图形在上,所以交集部分的颜色为新图形的颜色

        destination-atop:显示新图形和交集部分,新图形在下,所以交集部分的颜色为原有图形的颜色

        lighter:原有图形和新图形都显示,交集部分做颜色叠加

        xor:重叠飞部分不现实

        copy:只显示新图形

文字看得人眼花缭乱,特意画图一张:回头一看惊觉打错字,图片的原型为圆形,你懂的- –

以下为实验代码

结果是动态的切换各种组合

给图形绘制阴影


    context.shadowOffsetX :阴影的横向位移量(默认值为0)
    context.shadowOffsetY :阴影的纵向位移量(默认值为0)
    context.shadowColor :阴影的颜色
    context.shadowBlur :阴影的模糊范围(值越大越模糊)

先来个简单的例子

再来个书本上的五角星的例子

绘制图像 

绘图:context.drawImage
图像平铺:context.createPattern(image,type)

图像裁剪:context.clip()

像素处理:var imagedata=context.getImageData(sx,sy,sw,sh)


绘图 context.drawImage

context.drawImage(image,x,y)

        image:Image对象var img=new Image(); img.src=”url(…)”;

        x:绘制图像的x坐标

        y:绘制图像的y坐标

context.drawImage(image,x,y,w,h)

        image:Image对象var img=new Image(); img.src=”url(…)”;

        x:绘制图像的x坐标

        y:绘制图像的y坐标

        w:绘制图像的宽度

        h:绘制图像的高度

context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh):选取图像的一部分矩形区域进行绘制

image:Image对象var img=new Image(); img.src=”url(…)”;

        sx:图像上的x坐标
        sy:图像上的y坐标
        sw:矩形区域的宽度
        sh:矩形区域的高度
        dx:画在canvas的x坐标
        dy:画在canvas的y坐标
        dw:画出来的宽度
        dh:画出来的高度

    最后一个方法可能比较拗,还是上图吧

三个方法的运行结果如下:

图像平铺 context.createPattern(image,type)

    type:
        no-repeat:不平铺

        repeat-x:横方向平铺

        repeat-y:纵方向平铺

        repeat:全方向平铺

类似图形组合,给出动态的切换平铺类型代码

图像裁剪:context.clip()

context.clip()只绘制封闭路径区域内的图像,不绘制路径外部图像,用的时候

先创建裁剪区域

再绘制图像(之后绘制的图形都会采用这个裁剪区域,要取消这个裁剪区域就需要用到保存恢复状态,下面有讲)

给出圆形和星形的裁剪代码

像素处理:

获取像素颜色数组: var imagedata=context.getImageData(sx,sy,sw,sh)

    sx:cavas的x轴坐标点

    sy:canvas的y轴坐标点

    sw:距离x的宽度

    sh:距离y的高度

可以利用context.getImageData返回的一个像素颜色数组,顺序是所取像素范围的从左到右,从上到下,数组的元素是(所有图形,包括图片,和绘制的图形)每个像素的rgba
[r1,g1,b1,a1,r2,g2,b2,a2…]

设置像素颜色:context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
    对imagedata数组中的各个像素的r、g、b、a值进行修改,再调用putImageData方法进行绘制

        imagedata:修改后的imagedata

        dx:重绘图像的起点横坐标(重绘的起点和原来的图像一致的话就会把原来的图形覆盖掉,看起来就像是原来的图像变成现在的图像一样)

        dy:重绘图像的起点纵坐标

        //以下可选参数,设置重绘的矩形范围,如果缺省,默认会重绘所有的imegedata

        dirtyX:矩形左上角x轴坐标

        dirtyY:矩形左上角y轴坐标

        dirtyWidth:矩形长度

        dirtyHeight:矩形高度

 

绘制文字

填充文字:context.fillText(text,x,y)  

绘制文字轮廓 context.strokeText(text,x,y)


     text:要绘制的文字

     x:文字起点的x坐标轴

     y:文字起点的y坐标轴

     context.font:设置字体样式

     context.textAlign:水平对齐方式

          start、end、right、center

     context.textBaseline:垂直对齐方式

          top、hanging、middle、alphabetic、ideographic、bottom

     var length=context.measureText(text):计算字体长度(px)那么能不能计算高度啊,很遗憾,不能

保存和恢复状态
保存:context.save()
恢复:context.restore()


在上面的裁剪图片提过,一旦设定了裁剪区域,后来绘制的图形都只显示裁剪区域内的内容,要“取消”这个裁剪区域才能正常绘制其他图形,其实这个“取消”是利用save()方法和restore()方法来实现的。

    context.save():调用该方法,会保存当前context的状态、属性(把他理解成游戏存档)

    context.restore():调用该方法就能恢复到save时候context的状态、属性(游戏回档)

保存文件  canvas.toDataURL(MIME)


      在canvas中绘出的图片只是canvas标签而已,并非是真正的图片,是不能右键,另存为的,我们可以利用canvas.toDataURL()这个方法把canvas绘制的图形生成一幅图片,生成图片后,就能对图片进行相应的操作了。

结合setInterval制作动画


基本原理就是定时清除整个canvas重新绘制,下面给出“我弹、我弹、我弹弹弹”的代码 (额、名字而已)

小矩形在矩形区域移动,碰到矩形区域的边缘反弹

结语


历时一天半,本来以为可以玩转的,写下来才发现要玩转canvas还需要很多的实践,这个道理应该是适用所有的技术的,做人啊,就得谦虚点。本文如有错误,请及时留言给我纠正,希望能给正在学canvas绘图的童鞋有所帮助