QML <2> Canvas 自定义绘制 网易云歌单封面实现

QML <2> Canvas 自定义绘制 网易云歌单封面实现

前言

基于QML 实现 网易云歌单封面,参考图如下:
在这里插入图片描述

实现图如下:
在这里插入图片描述

一、背景图

最底层为Rectangle ,图片用AnimatedImage 显示,`

Rectangle {
    width: 200
    height: 220
    clip: true
    property  string msg: "26万"
    AnimatedImage {
        id: animatedImage
        x: 0
        y: 0
        width: 200
        height: 180
        source: "qrc:/img/img/109951166294262909.jpg"

二、音乐图标

在这里插入图片描述

音乐图标,使用Unicode 字符显示,代码如下:
Unicode 字符获取网址:https://unicode-table.com/cn/blocks/

 Text {
            id: unicode_text
            x: 8
            y: 149
            width: 19
            height: 27

            text: String.fromCodePoint(0x1D160)
            layer.smooth: true
            layer.wrapMode: ShaderEffectSource.ClampToEdge
            transformOrigin: Item.Center
            font.pixelSize: 28
            color: "white"
        }

三.播放量

在这里插入图片描述

播放量文字使用Canvas 绘制,代码如下:

property  string msg: "26万"
Canvas{
            id: msg_canvas
            x: 23
            y: 157
            width: 138
            height: 23
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                ctx.fillStyle = "white";
                ctx.lineWidth = 2;
                ctx.font="18px Georgia";
                ctx.beginPath();
                ctx.fillText(msg, 15,15,width);
                ctx.stroke();
            }
        }

四.播放图标

在这里插入图片描述

播放图标使用Canvas 绘制,由三角形和圆形组成,
代码如下(示例):

 Canvas{
            id: paly_canvas
            x: 167
            y: 151
            width: 25
            height: width
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                // 圆圈绘制
                ctx.strokeStyle = "white"
                ctx.lineWidth = 1
                ctx.beginPath()
                ctx.arc(width/2,height/2,width/2,0,Math.PI*2)
                ctx.stroke()
                //三角形绘制
                ctx.fillStyle = "white"
                ctx.strokeStyle = "white"
                ctx.beginPath()
                ctx.moveTo(width/4, height/4)
                ctx.lineTo(width/4, height/4*3)
                ctx.lineTo(width/4*3, height/2)
                ctx.closePath()
                ctx.fill()
                ctx.stroke()
            }
        }

五.歌单信息背景

歌单信息背景使用Canvas 绘制,
在这里插入图片描述
代码如下:

 Canvas{
            id: msg_background
            x: 0
            y: 143
            width: 200
            height: 39
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                ctx.clearRect(0, 0, width, height)
                ctx.strokeStyle = "rgba(54, 54, 54, 0.4)";
                ctx.fillStyle = "rgba(54, 54, 54, 0.4)";
                ctx.fillRect(0, 0,parent.width, parent.height)
                ctx.stroke()
            }
        }

六.歌单文字介绍

在这里插入图片描述
在这里插入图片描述

歌单文字介绍使用Canvas 绘制,可设置最多显示行数,超出行数使用“…”显示,代码如下:

Canvas{
        id: name_canvas
        x: 0
        y: 181
        width: 200
        height: 39
        onPaint: {
            var ctx = getContext("2d");
            ctx.fillStyle = "rgba(54, 54, 54, 1)";
            ctx.lineWidth = 2;
            ctx.font="14px Georgia";
            var str= "今天温柔的风归功于昨天的雨"
            draw_text_show(ctx,width-15,15,2,str);
        }
    }

    //ctx 画布
    // linewidth 行宽
    // lineheight  行高
    // maxline 最大行数
    // str 显示字符串
    function draw_text_show(ctx,linewidth,lineheight,maxline,str)
    {
        var strwidth = ctx.measureText(str).width;
        if(strwidth < linewidth)
        {
            ctx.fillText(str, 5, lineheight);
        }
        else
        {
            var curwidth = 0;
            var curline= 1;
            var maskstr = '...';
            var maskwidth = ctx.measureText(maskstr).width;
            var curstr="";
            var len = str.length;
            for( var i = 0; i < str.length; ++i )
            {
                var fontWidth = ctx.measureText(str[i]).width;
                var nextwidth = curwidth+fontWidth;

                var draw_all = false;

                //########
                //####...
                if(curline == maxline)
                {
                    nextwidth += maskwidth;
                    if(nextwidth <= linewidth)
                    {
                        curwidth += fontWidth;
                        curstr  +=  str[i];
                        if(i+1 < str.length)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        curstr += maskstr;
                        draw_all = true;
                         console.log(curstr)
                    }

                }
                else
                {
                    if( nextwidth <= linewidth )
                    {
                        curwidth += fontWidth;
                        curstr  +=  str[i]
                        continue;
                    }

                }

                ctx.fillText(curstr, 5, lineheight*curline);
                curline++;
                curwidth = 0;
                curstr="";
                if(draw_all)
                {
                    break;
                }
            }
        }
    }

总结

完整代码:

import QtQuick 2.12

Rectangle {
    width: 200
    height: 220
    clip: true
    property  string msg: "26万"
    AnimatedImage {
        id: animatedImage
        x: 0
        y: 0
        width: 200
        height: 180
        source: "qrc:/img/img/109951166294262909.jpg"

        Canvas{
            id: msg_background
            x: 0
            y: 143
            width: 200
            height: 39
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                ctx.clearRect(0, 0, width, height)
                ctx.strokeStyle = "rgba(54, 54, 54, 0.4)";
                ctx.fillStyle = "rgba(54, 54, 54, 0.4)";
                ctx.fillRect(0, 0,parent.width, parent.height)
                ctx.stroke()
            }
        }
        Text {
            id: unicode_text
            x: 8
            y: 149
            width: 19
            height: 27

            text: String.fromCodePoint(0x1D160)
            layer.smooth: true
            layer.wrapMode: ShaderEffectSource.ClampToEdge
            transformOrigin: Item.Center
            font.pixelSize: 28
            color: "white"
        }

        Canvas{
            id: msg_canvas
            x: 23
            y: 157
            width: 138
            height: 23
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                ctx.fillStyle = "white";
                ctx.lineWidth = 2;
                ctx.font="18px Georgia";
                ctx.beginPath();
                ctx.fillText(msg, 15,15,width);
                ctx.stroke();
            }
        }
        Canvas{
            id: paly_canvas
            x: 167
            y: 151
            width: 25
            height: width
            onPaint: {
                var ctx = getContext("2d")
                draw(ctx)
            }
            function draw(ctx )
            {
                // 圆圈绘制
                ctx.strokeStyle = "white"
                ctx.lineWidth = 1
                ctx.beginPath()
                ctx.arc(width/2,height/2,width/2,0,Math.PI*2)
                ctx.stroke()
                //三角形绘制
                ctx.fillStyle = "white"
                ctx.strokeStyle = "white"
                ctx.beginPath()
                ctx.moveTo(width/4, height/4)
                ctx.lineTo(width/4, height/4*3)
                ctx.lineTo(width/4*3, height/2)
                ctx.closePath()
                ctx.fill()
                ctx.stroke()
            }
        }
    }



    Canvas{
        id: name_canvas
        x: 0
        y: 181
        width: 200
        height: 39
        onPaint: {
            var ctx = getContext("2d");
            ctx.fillStyle = "rgba(54, 54, 54, 1)";
            ctx.lineWidth = 2;
            ctx.font="14px Georgia";
            var str= "今天温柔的风归功于昨天的雨今天温柔的风归功于昨天的雨今天温柔的风归功于昨天的雨"
            draw_text_show(ctx,width-15,15,2,str);
        }
    }

    //ctx 画布
    // linewidth 行宽
    // lineheight  行高
    // maxline 最大行数
    // str 显示字符串
    function draw_text_show(ctx,linewidth,lineheight,maxline,str)
    {
        var strwidth = ctx.measureText(str).width;
        if(strwidth < linewidth)
        {
            ctx.fillText(str, 5, lineheight);
        }
        else
        {
            var curwidth = 0;
            var curline= 1;
            var maskstr = '...';
            var maskwidth = ctx.measureText(maskstr).width;
            var curstr="";
            var len = str.length;
            for( var i = 0; i < str.length; ++i )
            {
                var fontWidth = ctx.measureText(str[i]).width;
                var nextwidth = curwidth+fontWidth;

                var draw_all = false;

                //########
                //####...
                if(curline == maxline)
                {
                    nextwidth += maskwidth;
                    if(nextwidth <= linewidth)
                    {
                        curwidth += fontWidth;
                        curstr  +=  str[i];
                        if(i+1 < str.length)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        curstr += maskstr;
                        draw_all = true;
                         console.log(curstr)
                    }

                }
                else
                {
                    if( nextwidth <= linewidth )
                    {
                        curwidth += fontWidth;
                        curstr  +=  str[i]
                        continue;
                    }

                }

                ctx.fillText(curstr, 5, lineheight*curline);
                curline++;
                curwidth = 0;
                curstr="";
                if(draw_all)
                {
                    break;
                }
            }
        }
    }
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值