ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Blazor组件自做二 : 使用JS隔离制作手写签名组件

2022-03-21 08:33:15  阅读:224  来源: 互联网

标签:function canvas cxt 自做 JS 组件 handwritten


Blazor组件自做二 : 使用JS隔离制作手写签名组件

本文相关参考链接

  1. JavaScript 模块中的 JavaScript 隔离
  2. Viewer.js工程
  3. Blazor组件自做一 : 使用JS隔离封装viewerjs库

Blazor JS 隔离优势

导入的 JS 不再污染全局命名空间。
库和组件的使用者不需要导入相关的 JS。即不需要再在ssr的 Pages/_Host.cshtml 或 Pages/_Layout.cshtml ,wasm的 wwwroot/index.html 里写
第一遍载入静态资产请求包含值为 no-cache 或 max-age(值为零 (0))的 标头。真正页面组件使用才载入真实大小文件。

继续Day2正文,以下基础步骤再走一遍,Day3之后不再赘述.

1. 打开VS2020, 新建工程面板, 项目模板搜索 blazor , 选择Blazor Server应用. (wasm也可以,但是不好调试,先从简单的SSR入手)

image

2. 工程名称改为Blazor100,下一步,默认设置, 保存.

image
image

3. 右键点击wwwroot文件夹,添加lib文件夹,添加handwritten子文件夹,里面添加handwritten.js文件, 添加handwritten.css文件 . 最终版本参考如下

image
image

4. 编写js文件. 主要是使用Canvas画线,附加功能可生成今日日期等等各位可以自行修改.
handwritten.js代码
export function init(wrapper, options) {
    console.log('start handwritten');



    /**
     * 格式化日期.
     */
    Date.prototype.format = function (fmt) {
        var o = {
            "M+": this.getMonth() + 1, //月份
            "d+": this.getDate(), //日
            "h+": this.getHours(), //小时
            "m+": this.getMinutes(), //分
            "s+": this.getSeconds(), //秒
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度
            "S": this.getMilliseconds() //毫秒
        };
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ?
                    (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            }
        }
        return fmt;
    }

    /**
     * 获取URL参数
     */
    function getQueryString(name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) return unescape(r[2]); return null;
    }
    /**
    * 是否数字
    */
    function isNumeric(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

    function myRedirect(nextw) {
        event.returnValue = false;//加这句
        this.location.href = nextw;
    }
    //当页面高度超过设备可见高度时,阻止掉touchmove事件。
    document.body.addEventListener('touchmove', function (e) {
        e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)
    }, { passive: false }); //passive 参数不能省略,用来兼容ios和android 


    new lineCanvas({
        el: document.getElementById("canvas"), //绘制canvas的父级div
        clearEl: document.getElementById("clearCanvas"), //清除按钮
        saveEl: document.getElementById("saveCanvas"), //保存按钮
        //      linewidth:1,//线条粗细,选填
        //      color:"black",//线条颜色,选填
        //      background:"#ffffff"//线条背景,选填
    });

    function lineCanvas(obj) {
        this.linewidth = 1;
        this.color = "#000000";
        this.background = "#ffffff";
        for (var i in obj) {
            this[i] = obj[i];
        };
        this.canvas = document.createElement("canvas");
        this.el.appendChild(this.canvas);
        this.cxt = this.canvas.getContext("2d");
        this.canvas.width = this.el.clientWidth;
        this.canvas.height = this.el.clientHeight;

        this.cxt.fillStyle = this.background;
        this.cxt.fillRect(0, 0, this.canvas.width, this.canvas.height);

        //this.cxt.fillStyle = "red";
        //this.cxt.font = "16px verdana";
        //this.cxt.textAlign = "left";

        ////fillText("要添加的文字",x0坐标,y0坐标)
        //var orderedtime = new Date().getTime();
        //orderedtime = (new Date(orderedtime)).format("yyyy-MM-dd  hh:mm");
        //this.cxt.fillText(orderedtime, 30, 30);

        this.cxt.fillStyle = this.background;
        this.cxt.strokeStyle = this.color;
        this.cxt.lineWidth = this.linewidth;
        this.cxt.lineCap = "round";
        //开始绘制
        this.canvas.addEventListener("touchstart", function (e) {
            this.cxt.beginPath();
            this.cxt.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
        }.bind(this), false);
        //绘制中
        this.canvas.addEventListener("touchmove", function (e) {
            this.cxt.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
            this.cxt.stroke();
        }.bind(this), false);
        //结束绘制
        this.canvas.addEventListener("touchend", function () {
            this.cxt.closePath();
        }.bind(this), false);
        //清除画布
        this.clearEl.addEventListener("click", function () {
            this.cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
        }.bind(this), false);
        //保存图片,直接转base64
        this.saveEl.addEventListener("click", function () {
            var imgBase64 = this.canvas.toDataURL();
            console.log(imgBase64);
            return wrapper.invokeMethodAsync("invokeFromJS", imgBase64);
        }.bind(this), false);
        //添加日期时间
        function adddatetime() {
            this.cxt.fillStyle = "red";
            this.cxt.font = "12px '微软雅黑'";
            this.cxt.textAlign = "left";
            //fillText("要添加的文字",x0坐标,y0坐标)
            var orderedtime = new Date().getTime();
            orderedtime = (new Date(orderedtime)).format("yyyy-MM-dd  hh:mm");
            this.cxt.strokeText(orderedtime, 50, 100);
        }
    };


}

export function destroy(options) { 
}
5. 编写 handwritten.css 文件. (细心的朋友应该发现,跟Day1不一样,这个css放在lib里面,留着大家思考 :-> )
handwritten.css代码
#canvas {
    width: 99%;
    /*max-width: 375px;*/
    height: 300px;
    position: relative;
    overflow: hidden;
    overflow: -Scroll;
}

    #canvas canvas {
        display: block;
    }

#clearCanvas0 {
    width: calc(50% - 5px);
    height: 40px;
    line-height: 40px;
    text-align: center;
    position: absolute;
    top: 300px;
    left: 5px;
    border: 1px solid #DEDEDE;
    z-index: 1;
}

#saveCanvas0 {
    width: calc(50% - 5px);
    height: 40px;
    line-height: 40px;
    text-align: center;
    position: absolute;
    top: 300px;
    right: 5px;
    border: 1px solid #DEDEDE;
    z-index: 1;
}
6. 点开或者新建Components文件夹 , 新建Handwritten.razor组件,签名会直接转化为Base64编码的string,同学们自己保存到数据库或者当作变量传递就行

image

组件的命名空间统一使用Blazor100.Components,在razor文件和razor.cs都使用统一命名空间,这样不会受到文件夹嵌套各种影响.

Handwritten.razor代码
@implements IAsyncDisposable
@namespace Blazor100.Components
@inject IJSRuntime JS

<link href="lib/handwritten/handwritten.css" rel="stylesheet" />

<div class="modal alert-popup" tabindex="-1" style="display:block" role="dialog">
    <div class="modal-dialog-w100">
        <div class="modal-content">
            <!-- Edit form for the current item -->
            <div id="canvas" style="height: 300px;">
            </div>
            <div>
                <button class="btn btn-secondary p-2 m-1 w-25" id="clearCanvas">清除</button>
                <button class="btn btn-primary p-2 m-1 w-25" id="saveCanvas">保存</button>
            </div>
        </div>
    </div>
</div>
@Result


@code {
    /// <summary>
    /// Handwritten 手写签名
    /// </summary>
    [Parameter]
    public EventCallback<string> HandwrittenBase64 { get; set; }

    /// <summary>
    /// 关闭扫码框回调方法
    /// </summary>
    [Parameter]
    public EventCallback Close { get; set; }


    /// <summary>
    /// 签名结果,签名会直接转化为Base64编码的string,保存到数据库或者当作变量传递都可以
    /// </summary>
    [Parameter]
    public string? Result { get; set; }

    private IJSObjectReference? module;

    // To prevent making JavaScript interop calls during prerendering
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!firstRender) return;
        module = await JS.InvokeAsync<IJSObjectReference>("import", "./lib/handwritten/handwritten.js");
        await module.InvokeVoidAsync("init", DotNetObjectReference.Create(this), null);
    }

    [JSInvokable("invokeFromJS")]
    public async Task ChangeValue(string val)
    {
        Result = val;
        StateHasChanged();
        await HandwrittenBase64.InvokeAsync(val);
        //return Task.CompletedTask;
    }


    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            //await module.InvokeVoidAsync("destroy",null);
            await module.DisposeAsync();
        }
    }
}

7. Pages文件添加HandwrittenPage.razor文件,用于演示组件调用.
HandwrittenPage.razor代码
@page "/handwritten"

<h3>Handwritten 手写签名</h3>
<h6>注意:只支持移动设备签名,桌面版浏览器测试请打开F12模拟为移动设备.</h6>

<button class="btn btn-primary"
        type="button"
        @onclick="(() => ShowHandwritten = !ShowHandwritten)">
    [签名]
</button>
<textarea type="text" class="form-control" style="min-width: 100px;" rows="10"
          @bind="DrawBase64"
          placeholder="Base64" />
@if (ShowHandwritten)
{

    <Handwritten HandwrittenBase64="(e => { DrawBase64=e; ShowHandwritten = !ShowHandwritten; })"
                 Close="(()=>ShowHandwritten=!ShowHandwritten)" />

}

@code{

    /// <summary>
    /// 显示签名界面
    /// </summary>
    bool ShowHandwritten { get; set; } = false;

    /// <summary>
    /// 签名Base64
    /// </summary>
    public string? DrawBase64 { get; set; }


}

8. _Imports.razor加入一行引用组件的命名空间,已经有这行就不需要再重复写了.
@using Blazor100.Components

image

9. 首页引用组件演示页 <HandwrittenPage />

image

10. F5运行程序,将会自动打开浏览器调试

image

image

image

签名结果会直接转化为Base64编码的string,保存到数据库或者当作变量传递都可以

至此,使用JS隔离制作手写签名组件大功告成! Happy coding!

Blazor组件自做系列

Blazor组件自做一 : 使用JS隔离封装viewerjs库
Blazor组件自做二 : 使用JS隔离制作手写签名组件

项目源码 Github | Gitee

标签:function,canvas,cxt,自做,JS,组件,handwritten
来源: https://www.cnblogs.com/densen2014/p/16028167.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有