24.Qt Quick QML-Canvas和Context2D详解
1.Canvas介绍
Canvas是一个允许绘制直线和曲线、简单和复杂的形状、图形和引用的图形图像。它还可以添加文本、颜色、阴影、渐变和图案,并执行低级别像素操作。Canvas输出可以另存为图像文件或序列化到URL。
例如,以下代码创建一个Canvas项目,该项目具有高度为100像素、宽度为200像素的绘图区域:
- import QtQuick 2.0
- Canvas {
- id: mycanvas
- width: 100
- height: 200
- onPaint: {
- var ctx = getContext("2d");
- ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
- ctx.fillRect(0, 0, width, height);
- }
- }
目前Canvas项仅支持Context2D。
Canvas常用属性如下所示:
- available : bool,该属性用于设置Canvs是否可用,只有为true时后续的操作才有效;
- canvasSize : size,画布大小,默认情况下,画布大小与当前Canvas的width和height相同.
- context : object,保存活动的绘图上下文。如果画布已经准备好,并且成功调用了getContext(),或者contextType属性已经设置了支持的上下文类型,那么这个属性将包含当前的绘图上下文,否则为空。
- contextType : string,保存绘图上下文的类型,对于Context2D,该值将为"2d"
- renderStrategy : enumeration,保存当前画布渲染策略,取值有以下几种:
- Canvas.Immediate - 在UI主线程中立即执行图形命令(默认)
- Canvas.Threaded - 当前要绘制的图形延迟到专用的线程里执行(不在UI主线程中立即执行)
- Canvas.Cooperative - 当前要绘制的图形延迟到应用程序的全局渲染线程
- renderTarget : enumeration,渲染目标.取值有以下几种:
- Canvas.Image -渲染到内存中的图像缓冲区(默认)
- Canvas.FramebufferObject -渲染到OpenGL帧缓冲区
Signals:
- imageLoaded() : 加载图像时发出此信号。
- paint(region) : 当需要渲染区域时,会发出此信号。我们可以在该信号接收器里写入要绘制的内容
- painted() : 在执行所有上下文绘制命令并渲染Canvas(onPaint之后)后发出。
Methods:
- cancelRequestAnimationFrame(handle) : 取消请求动画框架(句柄)
- object getContext(contextId, ... args) : 返回图形上下文,如果没有可用的上下文,则返回null。在第一次调用getContext之后,后续再次调用时都将返回相同的上下文对象
- isImageError(image) : 如果图像加载失败,则返回true,否则返回false。
- isImageLoaded(image) : 如果图像已成功加载并准备好使用,则返回true。
- isImageLoading(image) : 如果图像当前正在加载,则返回true。
- loadImage(image) : 异步加载图像。一旦图像准备好,将发出imageLoaded()信号。加载的图像可以使用unloadImage()方法卸载。
- markDirty(area) : 将给定区域标记为等待刷新的区域(只会刷新一次),只要该此区域为可见区,画布渲染器将重新绘制它。这将触发requestPaint信号。
- int requestAnimationFrame(callback) : 动画计时器,它会自动根据电脑配置来计算刷新帧率,一般与屏幕刷新频率一致,它的返回值是一个计数值,可以获取当前调用了callback多少次
- requestPaint() : 请求重新绘制整个可见区域,将会重新发出paint信号
- bool save(filename) :将当前画布内容保存到图像文件文件名中。保存的图像格式由文件名的后缀自动决定。成功时返回true,比如save("1.png")
- string toDataURL(mimeType) : 返回画布中图像的数据URL。mimeType参数默认为“image/png”。
- unloadImage(image) :卸载图像后,除非再次加载图像(loadImage()、Context2D::createImageData()和Context2D::drawImage()),否则画布上下文将无法绘制图像
示例如下所示:
- Canvas {
- id: canvas
- property int widthLen : 50
- width: 100
- height: 200
- onPaint: {
- var ctx = getContext("2d");
- var raf;
- function draw() {
- ctx.clearRect(0,0, canvas.width, canvas.height);
- ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
- ctx.fillRect(0, 0, widthLen, height);
- widthLen = (widthLen + 1) % canvas.width
- raf = requestAnimationFrame(draw);
- console.log("raf" + raf);
- }
- draw();
- }
- }
这里我们设置的是每到了屏幕刷新时间点,就将绘制的宽度将会加1,而getContext("2d")是用来获取Context2D对象.
requestAnimationFrame函数在动画中非常重要,比如我们要绘制一个移动的小球,我们就必须使用该函数,不能使用Timer定时器,因为Timer定时器和屏幕刷新时间点不一致,如果过快就导致过度绘制,增加开销,过慢就导致动画不流畅
接下来我们主要还是学习Context2D对象.
2.Context2D对象的属性和方法
参考https://www.w3school.com.cn/tags/html_ref_canvas.asp
Properties
- canvas : QtQuick::Canvas,保存当前Context2D要绘制的哪个画布
- fillRule : enumeration,填充规则,取值有以下几种:
- Qt.OddEvenFill : 奇偶填充
- Qt.WindingFill : 缠绕填充(默认值)
- fillStyle : variant.填充的样式,样式可以是包含CSS颜色字符串、CanvasGradient或CanvasPattern对象,比如:
- 'rgb(red, green, blue)' - for example: 'rgb(255, 100, 55)' or 'rgb(100%, 70%, 30%)'
- 'rgba(red, green, blue, alpha)' - for example: 'rgb(255, 100, 55, 1.0)' or 'rgb(100%, 70%, 30%, 0.5)'
- 'hsl(hue, saturation, lightness)'
- 'hsla(hue, saturation, lightness, alpha)'
- '#RRGGBB' - for example: '#00FFCC'
- Qt.rgba(red, green, blue, alpha) - for example: Qt.rgba(0.3, 0.7, 1, 1.0)
- CanvasGradient或CanvasPattern对象具体参考createLinearGradient(), createRadialGradient(), createPattern()
- font : string,字体设置,与 CSS font 属性相同,比如:
- font-style :规定字体样式。可能的值:normal、italic(斜体)、oblique(倾斜)
- font-variant : 规定字体变体。可能的值:normal、small-caps(所有小写字母均转换为大写,但是尺寸会变的更小)
- font-weight : 规定字体的粗细。可能的值:normal、bold(粗体)、bolder(更粗的粗体)、lighter(细体)、或者0~99数字
- font-size : 字号,后缀名可以为px(像素)、pt(磅数)
- line-height :行高,默认为line-height: 100%,如果比100%小,那么间距将会紧凑
- font-family: 字体族,常用的有serif、sans-serif、cursive、fantasy、monospace
- 可以按顺序设置如下属性:
- font-style
- font-variant
- font-weight
- font-size/line-height
- font-family
- 如果不设置其中的某个值,则使用默认值,比如: ctx.font = "30px sans-serif
- globalAlpha : real,保存应用于渲染操作的当前alpha值。该值必须在0.0(完全透明)到1.0(完全不透明)的范围内。默认值为1.0。
- globalCompositeOperation : string,组合模式,取值有:
- source-atop - A atop B. 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
- source-in - A in B. 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
- source-out - A out B. 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
- source-over - 默认。在目标图像上显示源图像。(default)
- destination-atop - B atop A.在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示
- destination-in - B in A. 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
- destination-out - B out A. 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
- lighter - A plus B. 显示源图像 + 目标图像.每一点都是先画的和后画的同一点的颜色之和,注意颜色的最大值为255。所以白色一直是白色
- copy - A (B is ignored). 显示源图像。忽略目标图像。
- xor - A xor B. 使用异或操作对源图像与目标图像进行组合。
- lineCap : string,绘制结束线帽的样式。它可能是下面的值之一:
- butt - 线的两端有垂直于线方向(默认值)
- round -线的两端有直径等于线宽的半圆
- square -线的两端有个,长等于线宽,宽等于1/2线宽的矩形。
- lineDashOffset : real,设置虚线偏移量。默认的线破折号偏移值为0。此属性是在QtQuick 2.11中引入的。另请参见getLineDash()和setLineDash()。
- lineJoin : string,两条线交汇时创建的拐角类型。当线的子路径上存在任何本属性的设置,它将在线的连续上共享本属性,可能的属性值如下:
- bevel - 创建斜角
- round - 创建圆角,直径为线宽,圆心为交汇点。
- miter - 创建尖角(默认值)
- lineWidth : real,线的宽度。如果填入<0的值,则被忽略
- miterLimit : real,设置尖角的最大长度,两条线交汇处内角和外角之间的距离,默认值为10.0
- shadowBlur : real,用于阴影的模糊距离。
- shadowColor : string,阴影颜色
- shadowOffsetX : qreal,阴影的水平偏移距离
- shadowOffsetY : qreal,阴影的垂直偏移距离
- strokeStyle : variant,笔划的颜色,用于线环绕形状的填充样式。样式能是CSS颜色, CanvasGradient或者CanvasPattern颜色。无效值被忽略。默认值是'#000000'。
- textAlign : string,文本对齐(文本的水平位置)方式,取值有:
- start(默认值)
- end
- left
- right
- center
- textBaseline : string,文本基线(文本的垂直位置)设置,取值有:
- top
- hanging
- middle
- alphabetic(默认值)
- ideographic
- bottom
Methods
- object arc(x, real y, real radius, real startAngle, real endAngle, bool anticlockwise)
- // 绘制弧线,圆心为(x,y),radius半径,起始结束角度startAngle、endAngle、anticlockwise逆时针(默认为true)
- object arcTo(x1, real y1, real x2, real y2, real radius)
- // 根据起点(x1,y1)和终点(x2,y2),还有radius半径来绘制弧线
- object beginPath()
- // 设置为新路径,并会重置当前路径,如果绘制线,调用它后切记要使用moveTo()来重新指定开始位置
- object bezierCurveTo(cp1x, real cp1y, real cp2x, real cp2y, real x, real y)
- // 由(cp1x,cp1y)和(cp2x,cp2y)控制线,在当前位置和给终点(x,y)之间添加一条三阶贝塞尔曲线。如果创建二次贝塞尔曲线请参考quadraticCurveTo()
- object clearRect(x, real y, real w, real h)
- // 将(x,y,w,h)指定的矩形中画布上的所有像素清除为透明色。
- object clip()
- //从当前路径创建裁剪区域,区域外的任何部分都不显示,使用clip()之前需要设置要裁剪的路径:
- //首先调用context.beginPath()设置起始路径。
- //通过调用lineTo、arcTo、arc、moveTo等方法的联合和closePath方法来定义剪切路径。
- //调用context.clip()方法来剪切区域
- //最后绘制时,只会显示裁剪的区域内的内容
- object closePath() //如果对象的路径没有子路径,则该方法将不执行任何操作。否则,创建从当前点到开始点的路径,
- object createConicalGradient(x, real y, real angle) // 返回一个CanvasGradient圆锥渐变对象,该渐变围绕中心点(x,y)逆时针插值颜色,起始角度角度角度2以弧度为单位。
- CanvasImageData createImageData(imageUrl) // 通过加载的imageUrl图像来创建CanvasImageData对象。注意:在此函数调用之前,必须已加载imageUrl,否则将返回空的CanvasImageData对象。
// 加载可以参考Canvas::loadImage()、QtQuick::Canvas::unloadImage()、和QtQuick::Canvas::isImageLoaded。- CanvasImageData createImageData(imageData) // 通过CanvasImageData来创建一个相同的CanvasImageData对象。
- CanvasImageData createImageData(sw, real sh) // 使用给定的宽高来创建一个空的CanvasImageData对象。
- object createLinearGradient(x0, real y0, real x1, real y1) // 创建一个CanvasGradient线性渐变对象.该渐变沿起点(x0,y0)和终点(x1,y1)之间的直线过渡颜色。颜色可以通过addColorStop()来插入
- variant createPattern(image, string repetition) // 用给定的image和repetition参数创建一个带图片的CanvasPattern调色板对象,image必须是个有效的对象,比如:CanvasImageData对象或已加载的imageUrl repetition取值有:
- "repeat" - both directions,xy方向重复填充(默认)
- "repeat-x - horizontal only,仅x方向
- "repeat-y" - vertical only,仅y方向
- "no-repeat" - neither
- variant createPattern(color, enumeration patternMode) : 根据给定的color和调色板填充样式,返回调色板对象。patternMode填充样式比如有:Qt.SolidPattern : 全部填充,具体参考Qt::BrushStyle.
- object createRadialGradient(x0, real y0, real r0, real x1, real y1, real r1) : 创建一个CanvasGradient半径渐变对象.返回一个起点为(x0,y0),半径r0;终点为(x1,y1),半径为r1的径向渐变
- drawImage(image, real sx, real sy, real sw, real sh, real dx, real dy, real dw, real dh) :将image上起始点(sx,sy),宽sw,高sh的图像,绘制到画布上起始点(dx,dy),宽dw,高dh的位置(可以实现缩放效果)
- 注意图片的类型可以是Image子类或图片的url地址或CanvasImageData对象。当提供Image子类时,如果图片没有完成装载,这个方法什么都不画。如果提供图片url,则需要loadImage()加载才能使用
- drawImage(image, real dx, real dy, real dw, real dh): 将提供的图片绘制到画布的起始点(dx,dy),宽dw,高dh的位置
- drawImage(image, real dx, real dy) : 将提供的图片绘制到画布的(dx,dy)位置
- object ellipse(x, real y, real w, real h) : 创建一个边界矩形为(x,y,w,h)的椭圆。然后将之作为闭合子路径添加到路径中。椭圆是顺时针方向的曲线,起点和完成点在0度(3点钟方向)
- object fill() :使用fillStyle属性来填充路径
- object fillRect(x, real y, real w, real h) : 使用fillStyle属性来绘制矩形
- object fillText(text, x, y) : 在给定位置(x,y)填充指定的文本
- CanvasImageData getImageData(x, real y, real w, real h) : 返回一个CanvasImageData对象,其中包含由(x,y,w,h)指定的画布矩形的图像数据。
- array getLineDash() : 获取虚线数组,另请参见setLineDash()和lineDashOffset。
- object isPointInPath(x, real y) : 如果点(x,y)位于当前路径中,则返回true。
- object lineTo(x, real y) : 从当前位置到(x,y)点绘制一条线。
- object measureText(text) : 获取一个具有宽度的对象,比如在绘制文本之前解文本的宽度:ctx.measureText(text).width
- object moveTo(x, real y) : 创建新路径,把路径移动到画布中的指定点,移动的时候不会创建线条
- object putImageData(imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight) : 将给定imageData对象中的数据绘制到画布上
- //(dx,dy) : ImageData 对象左上角的坐标
- //(dirtyX,dirtyY) : 可选。在画布上放置图像的坐标
- //(dirtyWidth,dirtyHeight) : 可选。在画布上绘制图像所使用的宽度。
- object quadraticCurveTo(cpx, real cpy, real x, real y) : 创建二阶贝塞尔曲线
- object rect(x, real y, real w, real h) : 创建矩形,但它并不会真正将矩形画出,只能调用stroke() 或 fill()后才会真正作用于画布。
- object reset() : 将上下文状态和属性重置为默认值。
- object resetTransform() :将转换矩阵重置为默认值(相当于调用setTransform(1, 0, 0, 1, 0, 0)),另请参考transform(), setTransform(), and reset().。
- object restore() : 恢复之前保存过的路径状态和属性,防止save后对Canvas执行的操作对后续的绘制有影响
- object rotate(angle) : 旋转当前绘图,angle以以弧度计,比如5度=5*Math.PI/180
- object roundedRect(x, real y, real w, real h, real xRadius, real yRadius) : 创建圆角矩形
- object save() : 保存当前环境的状态,比如fillStyle、strokeStyle、font等,如果save后调用了beginPath()将会重置路径,如果绘制线的话,需要再次moveTo()一次
- object scale(x, real y) : 缩放或者放大接下来的绘图,取值为浮点数,(1=100%, 0.5=50%, 2=200%, 依次类推)
- setLineDash(pattern) : 绘制虚线
- object setTransform(a, real b, real c, real d, real e, real f) : 会调用resetTransform()重置变换矩阵后再次构建新的矩阵
- a(水平缩放)、b(水平方向倾斜)、c(垂直方向倾斜)、d(垂直缩放)、e(水平移动)、f(垂直移动)
- object shear(sh, real sv) : 在水平方向上用sh,在垂直方向上用sv剪切转换矩阵。
- object stroke() : 使用strokeStyle来绘制 moveTo() 和 lineTo() 等方法定义的路径,类似于描边
- object strokeRect(x, real y, real w, real h) : 绘制矩形轮廓(无填充)
- object strokeText(text, x, y) : 绘制文本轮廓(无填充)
- object text(text, real x, real y) : 创建文本,但它并不会真正画出,只能调用stroke() 或 fill()后才会真正作用于画布。
- object transform(a, real b, real c, real d, real e, real f) : 和setTransform()不一样,会在前一个变换矩阵上构建新的矩阵,
- object translate(x, real y) : 将当前(x,y)作为转为开始位置
3.beginPath()和closePath()、save()和restore()
beginPath()和closePath()用来创建一个闭环的路径
save()和restore()用来实现保存当前状态以及恢复当前状态
需要注意的是:
- 如果save后调用beginPath()将会重置路径,如果绘制线的话,需要再次moveTo()一次.
- stroke()和fill()都会以“上一次beginPath”之后的所有路径为基础进行绘制,所以绘制线的时候,必须调用一次beginPath()重置路径一次.
示例如下所示:
- Canvas {
- id: mycanvas
- width:300
- height: 300
- onPaint: {
- var ctx = getContext("2d")
- ctx.strokeStyle = "red"
- ctx.fillStyle = "yellow"
- ctx.save() // 将笔划颜色保存起来
- ctx.beginPath()
- ctx.strokeStyle = "blue"
- ctx.moveTo(50.5,50.5) // 调用beginPath()后,如果我们要绘制线条,则需要使用moveTo()来重新指定开始位置
- ctx.lineTo(50.5,150.5)
- ctx.lineTo(150.5,150.5)
- ctx.closePath() // 关闭路径,此时会创建从当前点(70,100)到开始点(50,50)的路径
- ctx.stroke() // 绘制路径的颜色
- ctx.fill() // 填充路径内部颜色
- ctx.restore()
- ctx.beginPath()
- ctx.moveTo(50.5,50.5)
- ctx.lineTo(150.5,50.5)
- ctx.stroke()
- }
- }
效果如下所示:
我们这里+0.5,是因为lineWidth默认为1,假如从(50,50)绘制到(150,50)的时候, 此时整个线宽的Y坐标应该是45.5px~55.5px,而像素点无法做到小于1px,所以会变成2px的模糊线条.
而如果坐标位置不一定是整数的时候,我们应该设置取整:
- cxt.moveTo(parseInt(50)+0.5, parseInt(150)+0.5)
4.stroke()和fill()区别
区别在于stroke()是进行描边(不填充内部颜色)、fill是进行填充内部颜色(路径内部颜色)
我们以绘制文字为例,示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- ctx.strokeStyle = "red"
- ctx.fillStyle = "red"
- ctx.font = "30px sans-serif"
- ctx.beginPath()
- ctx.text("hello stroke",20,40)
- ctx.stroke()
- ctx.beginPath()
- ctx.text("hello fill",20,140)
- ctx.fill()
- }
效果如下所示:
5. lineCap线帽样式
取值有以下三种:
- butt - 线的两端有垂直于线方向(默认值)
- round -线的两端有直径等于线宽的半圆
- square -线的两端有个,长等于线宽,宽等于1/2线宽的矩形。
示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- ctx.lineWidth = 10
- ctx.strokeStyle = "red"
- ctx.lineCap = "butt"
- ctx.beginPath()
- ctx.moveTo(20,20)
- ctx.lineTo(200,20)
- ctx.stroke()
- ctx.strokeStyle = "green"
- ctx.lineCap = "round"
- ctx.beginPath()
- ctx.moveTo(20,60)
- ctx.lineTo(200,60)
- ctx.stroke()
- ctx.strokeStyle = "blue"
- ctx.lineCap = "square"
- ctx.beginPath()
- ctx.moveTo(20,100)
- ctx.lineTo(200,100)
- ctx.stroke()
- }
效果如下所示:
7. lineJoin拐角样式
代码很简单,就不贴了,效果如下所示:
8. setLineDash绘制虚线
虚线相关的属性和方法有: lineDashOffset 、getLineDash()、setLineDash(pattern)、
参考https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
我们设置虚线数组时,需要注意的是:
数组中元素个数是奇数的话,数组会默认把组内元素复制一份,例如,[5,15,25]将变成[5,15,25,5,15,25]。
下标奇数的元素是绘制虚线的尺寸,下标偶数的元素是用来设置虚线之间的间距
示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- ctx.lineDashOffset = 0; //设置虚线的偏移量(线不偏移,只是虚的位置偏移)
- ctx.setLineDash( [ 5, 15, 25] ); //实线部分和间隔部分依次是 [5,15,25,5,15,25]
- ctx.moveTo( 10, 10 );
- ctx.lineTo( 310, 10 );
- ctx.stroke();
- }
效果如下所示:
而lineDashOffset则是设置虚线偏移值,值为正数时,会将虚线往左偏移,为负时,则往右偏移.
蚂蚁线教程:
- property int offset: 0
- Canvas {
- id: canvas
- width:300
- height: 300
- onPaint: {
- var ctx = getContext("2d")
- ctx.clearRect(0,0, canvas.width, canvas.height);
- ctx.setLineDash([4, 2]);
- ctx.lineDashOffset = -offset;
- ctx.strokeRect(10,10, 100, 100);
- }
- }
- Timer {
- interval: 20
- repeat: true
- running: true
- triggeredOnStart: true
- onTriggered: {
- offset++;
- if (offset > 16) {
- offset = 0;
- }
- canvas.requestPaint()
- }
- }
9.shadow阴影
shadow相当于一个物体的影子,context2D中关于shadow相关属性有:
- shadowBlur : real,用于阴影的模糊距离。
- shadowColor : string,阴影颜色
- shadowOffsetX : qreal,阴影的水平偏移距离
- shadowOffsetY : qreal,阴影的垂直偏移距离
示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- ctx.shadowBlur = 7
- ctx.shadowColor = "black"
- ctx.fillStyle ="black"
- ctx.beginPath();
- ctx.moveTo(20,20);
- ctx.lineTo(20,70);
- ctx.lineTo(70,70);
- ctx.closePath();
- ctx.rect(100,20,40,40);
- ctx.fill();
- }
效果如下所示:
10. clip示例
比如我们从一个矩形中裁剪一个三角形出来,示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- ctx.fillStyle = "red"
- ctx.beginPath(20,20)
- ctx.moveTo(20,20)
- ctx.lineTo(20,70)
- ctx.lineTo(70,70)
- ctx.closePath()
- ctx.clip()
- ctx.fillRect(20,20,100,100)
- }
11. createConicalGradient渐变示例
方法定义如下所示:
- object createConicalGradient(x, real y, real angle)
- //返回一个CanvasGradient圆锥渐变对象,该渐变围绕中心点(x,y)逆时针插值颜色,起始角度以弧度为单位(0度对应3点钟方向)
示例如下所示:
- onPaint: {
- var ctx = getContext("2d")
- var grd=ctx.createConicalGradient(50,50,180 * Math.PI / 180); // 设置起点为9点方向
- grd.addColorStop(0,"red");
- grd.addColorStop(0.25,"green");
- grd.addColorStop(0.5,"blue");
- grd.addColorStop(0.75,"black");
- grd.addColorStop(1.0,"red");
- // Fill with gradient
- ctx.fillStyle=grd;
- ctx.fillRect(0,0,50*2,50*2);
- }
- }
效果如下所示:
12. createRadialGradient渐变示例
方法如下所示:
- object createRadialGradient(x0, real y0, real r0, real x1, real y1, real r1)
- //创建一个CanvasGradient半径渐变对象.返回一个内圆为(x0,y0),半径r0;外圆为(x1,y1),半径为r1的径向渐变
- // 需要注意的起点圆的颜色永远都是起点0的颜色,而起点1的颜色,永远是外圆最外的颜色
示例如下所示:
- var ctx = getContext("2d")
- var grd=ctx.createRadialGradient(50,50,10,50,50,50);
- grd.addColorStop(0,"red");
- grd.addColorStop(0.1,"blue");
- grd.addColorStop(1.0,"green");
- // Fill with gradient
- ctx.fillStyle=grd;
- ctx.fillRect(0,0,50*2,50*2);
效果如下所示:
可以看到红色部分的宽度为20,这是因为我们内圆的半径恰好为10.
13. createPattern示例
createPattern()类似于调色板,用来实现重复绘制同一个数据,数据来源可以来自一张图片,也可以是Qt::BrushStyle样式的颜色.
如果是图片的话,需要使用Canvas的loadImage()加载到画布才能够使用.
比如给一个路径内部贴上图片.
- Canvas {
- id: mycanvas
- width:300
- height: 300
- onPaint: {
- var ctx = getContext("2d")
- var imge = ctx.createPattern("qrc:/wall", "repeat")
- ctx.fillStyle = imge
- ctx.beginPath()
- ctx.moveTo(200,30)
- ctx.lineTo(150,80)
- ctx.lineTo(150,130)
- ctx.lineTo(250,130)
- ctx.lineTo(250,80)
- ctx.closePath()
- ctx.fill()
- }
- Component.onCompleted: {
- mycanvas.loadImage("qrc:/wall")
- }
- onImageLoaded: {
- requestPaint()
- }
- }
14. CanvasImageData对象
CanvasImageData用来保存一块区域或一幅图片的像素数据,它的属性有:
- data : object,是个一字节的一维数组,包含着RGBA格式的整型数据(按照红,绿,蓝和透明值的顺序),范围在0至255之间(包括255)。
- height : int,图片高度
- width : int,图片宽度
比如我们获取指定的rowIndex、columnIndex的像素点rgba值时,可以这样写:
- r = imageData.data[((rowIndex * (imageData.width * 4)) + (columnIndex * 4)) + 0];
- g = imageData.data[((rowIndex * (imageData.width * 4)) + (columnIndex * 4)) + 1];
- b = imageData.data[((rowIndex * (imageData.width * 4)) + (columnIndex * 4)) + 2];
- a = imageData.data[((rowIndex * (imageData.width * 4)) + (columnIndex * 4)) + 3];
图片灰度效果,示例如下所示:
- Canvas {
- id: mycanvas
- width:300
- height: 300
- onPaint: {
- var ctx = getContext("2d")
- var ImageData = ctx.createImageData("qrc:/wall")
- for (var i = 0; i < ImageData.data.length; i += 4) {
- var avg = (ImageData.data[i] + ImageData.data[i + 1] + ImageData.data[i + 2]) / 3;
- ImageData.data[i] = avg; // red
- ImageData.data[i + 1] = avg; // green
- ImageData.data[i + 2] = avg; // blue
- }
- var imge = ctx.createPattern(ImageData, "repeat")
- ctx.fillStyle = imge
- ctx.beginPath()
- ctx.moveTo(200,30)
- ctx.lineTo(150,80)
- ctx.lineTo(150,130)
- ctx.lineTo(250,130)
- ctx.lineTo(250,80)
- ctx.closePath()
- ctx.fill()
- }
- Component.onCompleted: {
- mycanvas.loadImage("qrc:/wall")
- }
- onImageLoaded: {
- requestPaint()
- }
- }
未完待续,下章我们来通过Canvas实现一个合成大西瓜游戏
24.Qt Quick QML-Canvas和Context2D详解的更多相关文章
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Qt零基础教程(四) QWidget详解篇
在博客园里面转载我自己写的关于Qt的基础教程,没次写一篇我会在这里更新一下目录: Qt零基础教程(四) QWidget详解(1):创建一个窗口 Qt零基础教程(四) QWidget详解(2):QWid ...
- Qt零基础教程(四)QWidget详解(3):QWidget的几何结构
Qt零基础教程(四) QWidget详解(3):QWidget的几何结构 这篇文章里面分析了QWidget中常用的几种几何结构 下图是Qt提供的分析QWidget几何结构的一幅图,在帮助的 Wind ...
- canvas arcTo()用法详解 – CodePlayer
canvas arcTo()用法详解 – CodePlayer canvas arcTo()用法详解
- C++框架_之Qt的信号和槽的详解
C++_之Qt的信号和槽的详解 1.概述 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal ...
- C++框架_之Qt的窗口部件系统的详解-上
C++框架_之Qt的窗口部件系统的详解-上 第一部分概述 第一次建立helloworld程序时,曾看到Qt Creator提供的默认基类只有QMainWindow.QWidget和QDialog三种. ...
- canvas绘图API详解
canvas绘图API详解 1.context的状态 矩阵变换属性 当前剪辑区域 context的其他状态属性: strokeStyle, fillStyle, globalAlpha, lineWi ...
- Qt Quick之Canvas
QML中的Canvas,俗称画布,它用来定义一个绘图区域,可以使用ECMAScript代码来绘制直线,矩形,贝塞尔曲线,弧线,图片,文字等图元,还可以为这些图元应用填充颜色和边框颜色,甚至还可以进行低 ...
- Qt Quick QMl学习笔记 之图片浏览器
Qt Quick模块是编写QML应用程序的标准库.虽然Qt QML模块提供QML引擎和语言基础结构,但Qt Quick模块提供了使用QML创建用户界面所需的所有基本类型.它提供了一个可视画布,包括用于 ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
随机推荐
- java例题_03 水仙花数
1 /*3 [程序 3 水仙花数] 2 题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身. 3 例如:153 是一个 ...
- [Fundamental of Power Electronics]-PART II-7. 交流等效电路建模-7.4 规范电路模型
7.4 规范电路模型 在讨论了推导开关变换器交流等效电路模型的几种方法后,让我们先停下来,说明下这些结果.所有的在 CCM下以PWM工作的DC-DC变换器都具有相似的基本功能.首先,他们在理想情况下, ...
- inline®ister
inline关键字: 内联只是一个请求,不代表编译器会响应:同时某些编译器会将一些函数优化成为内联函数. C++在类内定义的函数默认是内联函数,具体是否真变成内联函数还需看编译器本身. registe ...
- 强大的工具(一):Capslock+ 3.x版本
1 概述 作者终于把Capslock+更新到了3.x版本了,所以就更了这篇博客. 2.x版本的可以戳这里. 3.x版本与2.x版本的主要不同是更新了新的键盘布局,更加顺手,下面让我们一起来看一下吧. ...
- 通过Python实现对SQL Server 数据文件大小的监控告警
1.需求背景 系统程序突然报错,报错信息如下: The transaction log for database '@dbname' is full. To find out why space in ...
- 7.bug生命周期
new:测试发现并提交bug,状态为new/active; open: 分配bug到开发人员,状态为open: fixed:开发人员处理完bug,将状态改为fixed: closed/reopen:测 ...
- Spring Cloud & Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(JMeter模拟测试)
目录 一. Sentinel概念 1. 什么是Sentinel? 2. Sentinel功能特性 3. Sentinel VS Hystrix 二. Docker部署Sentinel Dashboar ...
- Dubbo学习笔记(一) 基础知识HelloWorld
Dubbo是由阿里巴巴研发出的一款基于Java实现的RPC框架,现由Apache进行维护管理,笔记中使用zookeeper作为注册中心,dubbo+zookeeper环境安装教程:https://ww ...
- Tomcat配置及网站创建教程(IDEA)
Tomcat在本机的配置 解压 解压Tomcat压缩包后就算安装完成,解压完成生成文件夹 配置环境变量 1.配置JAVA_HOME 控制面板--系统--查看高级系统设置--环境变量--系统环境变量 新 ...
- CSS新特性contain,控制页面的重绘与重排
在介绍新的 CSS 属性 contain 之前,读者首先需要了解什么是页面的重绘与重排. 之前已经描述过很多次了,还不太了解的可以先看看这个提高 CSS 动画性能的正确姿势. OK,下面进入本文正题, ...