美文网首页前端技巧
合同模板动态生成水印的优化历程

合同模板动态生成水印的优化历程

作者: 恬雅过客 | 来源:发表于2023-01-11 16:41 被阅读0次

    由于三方的报表软件做报表不错,可要做合同模板的有些功能实现不了。故用前端画html实现合同模板页面,一开始合同模板编辑后打印,用的浏览器的打印功能,后续因为电子签就引入了三方html转pdf的工具wkhtmltopdf。合同水印就需要同时兼容chrome浏览器打印和工具wkhtmltopdf转pdf后打印的效果。

    各方案比较

    方案 支持动态生成水印 chrome浏览器打印 wkhtmltopdf工具打印
    第一阶段 ×
    第二阶段 ×
    第三阶段svg ×
    第三阶段canvas\color{red}{推荐}

    *个人推荐:如果你没用wkhtmltopdf工具,选第三种、第四种都行;用了wkhtmltopdf工具,选第四种。

    注:wkhtmltopdf由于最后的版本是2000年左右,之后好像没维护了。它内置的浏览器对es6及以上版本的js支持性比较差,尽量别用,不然会出现各种状况。

    第一阶段:js动态添加多个文本标签

    • 功能需求: 根据合同状态(合同草稿、已签约、已备案等等)生成对应的水印。

    • 大体实现思路:根据页面的内容的宽高,每个水印的大小来动态生成一组水印标签,动态遍历添加到body里,通过样式的positon:absolute;控制每个水印标签位置。

    • 代码参考:代码比较多,并且网上类似思路的文章不少,给个类似思路的参考链接:http://t.zoukankan.com/GongQi-p-4074609.html

    • 缺点: 在两种打印模式(chrome浏览器打印、工具wkhtmltopdf转pdf打印)中,任何一个合同都会有强制分页的情况(比如,合同封面、附件的每个附件单独提页等等),而一旦出现强制分页时,无论怎么获取合同页面的宽高都无法做到和打印页时一样的总高,导致最后几个打印页内容无合同水印,甚至水印重叠的问题。

    第二阶段:纯css实现,background-repeat: repeat;实现多个水印

    • 功能需求: 根据合同状态(合同草稿、已签约、已备案等等)生成对应的水印。(和第一阶段一致

    • 大体实现思路: 将所有可能的合同状态的水印枚举出来(合同草稿、已备案、已签约),然后让ui按指定尺寸设计成图片,然后将图片转成对应的base64码值,添加到样式里,用background-repeat: repeat;实现多个水印。

    • 代码参考: 核心代码如下:

        /*水印*/
        .watermark{
            display: none;
            position: fixed;
            z-index: -1;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-repeat: repeat;
            background-position: 0 0;
            background-size: 220px 220px;
        }  
        /*合同草稿*/
        .watermark.water-draft{
            display: block;
            background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQBAMAAABykSv/AAA9EWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS41LWMwMTQgNzkuMTUxNDgxLCAyMDEzLzAzLzEzLTEyOjA5OjE1ICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpPC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx4bXA6Q3JlYXRlRGF0ZT4yMDE5LTExLTA3VDE3OjAzOjE1KzA4OjAwPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOS0xMS0wN1QxNzowMzoxNSswODowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTktMTEtMDdUMTc6MDM6MTUrMDg6MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wTU06SW5zdGFuY2VJRD54bXAuaWlkOmI1MDljMGE3LWNjOTYtYTY0ZC1iZTU2LTdiYTMxMjBhM2U3MjwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDpmODFhNzgzYi0wOWQ5LWM4NDUtYWMyOS0xNGJlYjExMjY3NWI8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpmODFhNzgzYi0wOWQ5LWM4NDUtYWMyOS0xNGJlYjExMjY3NWI8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZjgxYTc4M2ItMDlkOS1jODQ1LWFjMjktMTRiZWIxMTI2NzViPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE5LTExLTA3VDE3OjAzOjE1KzA4OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDpiNTA5YzBhNy1jYzk2LWE2NGQtYmU1Ni03YmEzMTIwYTNlNzI8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTktMTEtMDdUMTc6MDM6MTUrMDg6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwveG1wTU06SGlzdG9yeT4KICAgICAgICAgPHBob3Rvc2hvcDpUZXh0TGF5ZXJzPgogICAgICAgICAgICA8cmRmOkJhZz4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxwaG90b3Nob3A6TGF5ZXJOYW1lPuWQiOWQjOiNieeovzwvcGhvdG9zaG9wOkxheWVyTmFtZT4KICAgICAgICAgICAgICAgICAgPHBob3Rvc2hvcDpMYXllclRleHQ+5ZCI5ZCM6I2J56i/PC9waG90b3Nob3A6TGF5ZXJUZXh0PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxwaG90b3Nob3A6TGF5ZXJOYW1lPuW3suWkh+ahiDwvcGhvdG9zaG9wOkxheWVyTmFtZT4KICAgICAgICAgICAgICAgICAgPHBob3Rvc2hvcDpMYXllclRleHQ+5bey5aSH5qGIPC9waG90b3Nob3A6TGF5ZXJUZXh0PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxwaG90b3Nob3A6TGF5ZXJOYW1lPuW3sue9keetvjwvcGhvdG9zaG9wOkxheWVyTmFtZT4KICAgICAgICAgICAgICAgICAgPHBob3Rvc2hvcDpMYXllclRleHQ+5bey572R562+PC9waG90b3Nob3A6TGF5ZXJUZXh0PgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QmFnPgogICAgICAgICA8L3Bob3Rvc2hvcDpUZXh0TGF5ZXJzPgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOklDQ1Byb2ZpbGU+c1JHQiBJRUM2MTk2Ni0yLjE8L3Bob3Rvc2hvcDpJQ0NQcm9maWxlPgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj40MDA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NDAwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz5ljlyFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAFVBMVEX////d3d35+fnz8/Pg4ODq6url5eW9fZpgAAAF10lEQVR42uzdvXacSBCG4XIjiPWpgRhZY8Vg2Y4F2uMY7F3H07I9938Je4ACGqwL2G+23kQcReBniubnaCyWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmWZVmW9b/tUyVXUYJOrqIGeXUdIHog/CDoDOS/0vtrAWm/TSCPQl4KBKBz7Zl/zkeQE0qhzrXABAJwk2QLCMhJPrQLCPDMTaIg9CTNDFIMAM6Od04SBenTaaOkB5F03jizg8gwb5RXAgIloQfhJHn4A4R0NQmvpwNIQUmSAB/b0SFfQeqGcUrugfI0OqBXEC8JI0kLFPNVY76AJEJIkukuBwALSKgJSRp94vAILCAZPB+Jw0gwFjYQYCIphKgTZpGLZBsIlKQSlnQ0OslwlrCBKElPNeoTSUAp2QrSAl64hmTA1NdprxeQMhlJ6A6kCKoiC8h5OpUBqIWmpMU5wzwnsp6y5Ibv5v0xFwkbiJdmnXd0wtSryL2uJcNytvoCfAt8T+ZVpPn9GUoCFJK0Xlj6KGM6EN3osZCgF0lrmkHXz46etTCmJKUw1czTnGEtX6ekJnzR5trxAKaKdCGpqUD0YuqEbhqTl8GLknjhabtOd39VKcbe16IkNCCuVxB9D+qWBXAmccLSqVAQbbnRFSVhybUICqI1exIaEGAPIu/ARqIgmECSTrQUuEQklXA0KEiTV9s5zAclIRqSdH5KnQALiQPKbCXhucqaRRpgJQlAvZB4qkUdeIAS6K/6haSiAoFvgI3EDbgTJSEDeQJiEjcUoiRMIMUwg0QE7pcwkbiXCaRPR5DXNiZIKn00T9EJT7qGAKXcY0/gAkq2RX36tx9wmIqMBwQRSBpNiXYRjsIRREmcaJVwlB1A8k8zSdMTvvqEX0D01U4hCQrhKsFYvYJUCYB+BFISukVdQaSZQQBPCOLfAEFPB9K+CVLQgRTZlYD0ciUgItcCktCDyEAPoqX8INowg6BaQUo2ECXpxWEUWUCAnzEI3cTnCqL1wpjuv4KADuT3jkRBWj6QG/Q7krvplJXygQQUO5JyXkPCuMkFggOJ3hiOnalAsCOZ6nUjpwI5kiiIkjCBHEkUpAVQcoHEJAqiJ66OCWTYkyiI/qUFEYhPDiQKIpJygdTS7Em2+5C/qUBE9iROQcZNLhA5kCiIRgRyqnckG4hwgbjWKwk7CKAk7CDAnZKwg6CXiCTjBSn2J65ADCIxySMxSBWTuJoWxH3dkfCCnHCOSXhBWpQLCTkIVhJyEGwk5CDAs5Jwg0QkNTVIu03JMzOIP20kXniadjsGqZ2SBK4h0d0OK4gem74NpSPJVhA9tlpF+EhWEP2pM0JGksvDAqI/9axFSLIHIVxH1uFOAaBaQAb9ZDGSDAA6BUkVhJYkr2aQk4LwkrzopDQKQkuyfKRcUBBWkvUjlSgIMUktGjmJl33Ma0kc9VpC2Yf6SNILT9Uq8QX1gaQQntLzwtEqwEZCBTKcJ4TPATNDTPIPEwjyy+USMPcsMQlVA+JuZUdCBbLrTmISXpCyFlaSAVHfq+PdO08NtrxobCQqUvy4XL4/rV8JQjol9zrgiX4V28uepKY7kGb5brw6JvFcIhFICx+T1FwHEoMgJvFcZ627GAQxSS1cIjGIkmhsIjEI4FkP5DYC4SUZgNsYpGUlCcBzBFJkrCQt8DMC6SWQkgBoIxARUhIHYAcijpMkAbADYSVJ9yD6K0KSmyOI3jPmQta7t0HQES7sRXgDpCJc2H12BMlDx7ge3skRpMsqxmXkWY4glVAuI/0fIKT/pWHNDaK5hx/VEYT8lSE1iBYAeHaQ7TKRH0SckigIPckCQk+iIPwkCsJPoiDkJDEIPwk/yPGRA/9aciUknVwFic46P4mC0Od+KQh9TizLsizLsizLsizLsv5tDw4JAAAAGAb1b30z9QwAAAAAAAAAAAAAAAAAAAAAAAAA5A2WClcnPfKqLQAAAABJRU5ErkJggg==");
        }
    
    • 效果图:
      效果图3.png
    • 缺点: 每新增一种合同状态,需要重新用新图转base64码值,还得改动合同页面html代码。

    第三阶段:cavas(或svg)转图片的base64码值,结合第二种阶段的思路。

    • 功能需求: 在第二阶段的基础上,用户提出要用合同编号做合同水印,每个业务件对应的合同编号不一样,故需要动态生成水印效果,这会儿单行文本。结果隔了一周左右,又一个地方的用户提出需要显示多行文本的水印(城市名、平台名称、合同编号、签约时间)。

    • 大体实现思路: 将canvas或svg转base64码值,然后结合第二阶段的思路。

    svg实现方式

    • 代码参考: demo页面代码如下:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="Access-Control-Allow-Origin" content="*">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <meta name="format-detection" content="telephone=no">
        <title>svg动态生成合同水印(转pdf的工具生成的码值不一样,故pdf没法生成水印)</title>
        <script src="jquery.js"></script>
    
        <style type="text/css">
            body{
                font-family:-apple-system-font,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif;
                color: #000;
            }
            .water{
                background-color: transparent;
                background-repeat: repeat;
                background-position: 0 0;
                background-size: 220px 220px;
            }
            .svg-wrap{
                width: 220px;
                height: 220px;
                border: 1px solid #f00;
            }
            .svgimg,
            #detail{
                margin-bottom: 20px;
                width: 500px;
                min-height: 240px;
                /* background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJteXN2ZyIgaGVpZ2h0PSIyMjAiIHdpZHRoPSIyMjAiIGVuY29kaW5nPSJ1dGYtOCI+CiAgICAgICAgICAgIDx0ZXh0IGZpbGw9IiNmMDAiIGZvbnQ9ImJvbGQg5a6L5L2TIiBmb250LXNpemU9IjMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiB0cmFuc2Zvcm09InJvdGF0ZSgtNDUsMTEwLDExMCkiIHg9IjExMCIgeT0iMTEwIiBlbmNvZGluZz0idXRmLTgiPuW3suWkh+ahiDwvdGV4dD4KICAgICAgICA8L3N2Zz4='); */
                background-repeat: repeat;
                background-position: 0 0;
                background-size: 100px 100px;
    
                word-break: break-all;
            }
        </style>
    </head>
    <body class="">     
        <!-- XT20220708151515 已备案-->
        <!-- font="bold 宋体"  -->
        <h4>待转换的svg:水印文本:XT20220708151515、已备案</h4>
        <div class="svg-wrap">
            <svg id="mysvg" height="220" width="220" encoding="utf-8">
                <text fill="#f00" font-size="30" text-anchor="middle" dominant-baseline="middle" transform="rotate(-45,110,110)" x="110" y="110" encoding="utf-8">已备案</text>
            </svg>
        </div>
    
        <h4>svg转换后的img的base64码值和背景图渲染效果:</h4>
        <div class="svgimg" id="water"></div>
    
        <div>
            网页版、wkhtmltopdf工具时,生成的base64码值是否一致:<span class="dev"></span>
        </div>
        <!-- https://www.bootcdn.cn/Base64/ -->
        <!-- <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/Base64/1.1.0/base64.min.js"></script> -->
    <script>
        //初始化加载
        $(function () {
            //网页版,生成的base64码值
            //已备案
            var page64 = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJteXN2ZyIgaGVpZ2h0PSIyMjAiIHdpZHRoPSIyMjAiIGVuY29kaW5nPSJ1dGYtOCI+CiAgICAgICAgCTx0ZXh0IGZpbGw9IiNmMDAiIGZvbnQtc2l6ZT0iMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiIHRyYW5zZm9ybT0icm90YXRlKC00NSwxMTAsMTEwKSIgeD0iMTEwIiB5PSIxMTAiIGVuY29kaW5nPSJ1dGYtOCI+5bey5aSH5qGIPC90ZXh0PgogICAgICAgIDwvc3ZnPg==';
            //XT20220708151515
            // page64 = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJteXN2ZyIgaGVpZ2h0PSIyMjAiIHdpZHRoPSIyMjAiIGVuY29kaW5nPSJ1dGYtOCI+CiAgICAgICAgCTx0ZXh0IGZpbGw9IiNmMDAiIGZvbnQtc2l6ZT0iMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiIHRyYW5zZm9ybT0icm90YXRlKC00NSwxMTAsMTEwKSIgeD0iMTEwIiB5PSIxMTAiIGVuY29kaW5nPSJ1dGYtOCI+WFQyMDIyMDcwODE1MTUxNTwvdGV4dD4KICAgICAgICA8L3N2Zz4=';
            //wkhtmltopdf工具,生成的base64码值
            var tool64 = 'data:image/svg+xml;base64,PHN2ZyBpZD0ibXlzdmciIGhlaWdodD0iMjIwIiB3aWR0aD0iMjIwIiBlbmNvZGluZz0idXRmLTgiPgogICAgICAgIAk8dGV4dCBmaWxsPSIjZjAwIiBmb250LXNpemU9IjMwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIiB0cmFuc2Zvcm09InJvdGF0ZSgtNDUsMTEwLDExMCkiIHg9IjExMCIgeT0iMTEwIiBlbmNvZGluZz0idXRmLTgiPuW3suWkh+ahiDwvdGV4dD4KICAgICAgICA8L3N2Zz4=';
    
            function svgBase64() {
                var svg = document.getElementById('mysvg');
                var s = new XMLSerializer().serializeToString(svg);
    
                // 方法一
                s = unescape(encodeURIComponent(s));//btoa、atoa不支持中文,用unescape处理
                var svgBase64 = window.btoa(s);
                svgBase64 = window.decodeURIComponent(svgBase64);
    
                // 方法二
                // s = decodeURIComponent(encodeURIComponent(s));//unescape已经过时废弃,换成uri处理
                // var svgBase64 = window.btoa(reEncode(s));
                // svgBase64 = svgBase64;
    
                // 方法三
                // var svgBase64 = Base64.encode(s);//base64.min.js
    
                var imgBase64 = 'data:image/svg+xml;base64,'+svgBase64;
                console.log({code:imgBase64});
                console.log(tool64);
                $('.dev').html(imgBase64==page64?'是':'否');
                var imgStr = "background-image: url('"+imgBase64+"');";
                $('.svgimg').html(imgStr);
                $('.svgimg').attr('style',imgStr);
            }
    
            function reEncode(data) {
                return decodeURIComponent(
                    encodeURIComponent(data).replace(/%([0-9A-F]{2})/g, function(match, p1) {
                        const c = String.fromCharCode('0x'+p1);
                        return c === '%' ? '%25' : c;
                    })
                )
            }
            
    
            svgBase64();
    
        });
    
    
    </script>
    </body>
    </html>
    

    -效果图:

    效果图2.jpg
    • 缺点: 虽然chrome浏览器打印能满足,但是工具wkhtmltopdf转pdf打印,水印效果消失。问题点:网页上svg转base64的生成的码值和工具wkhtmltopdf内置浏览器生成的码值不一致,并且后者生成的base64码值单独拿出来放浏览器的也无法显示,放console里,点击后只能解析成svg,不能解析成图片。如下图:
      svg1.jpg

    canvas实现方式\color{red}{推荐}

    • 代码参考: demo页面代码如下:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="Access-Control-Allow-Origin" content="*">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <meta name="format-detection" content="telephone=no">
        <title>canvas动态生成合同水印(多行文本)</title>
        <script src="jquery.js"></script>
    
        <style type="text/css">
            body{
                font-family:-apple-system-font,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif;
                color: #000;
            }
            .red{
                color: #f00;
                padding-right: 6px;
            }
            /*水印*/
            .watermark{
                display: none;
                position: fixed;
                z-index: -1;
                left: 0;
                top: 0;
                width: 100%;
                /*height: 1134px;*/
                height: 100%;
                background-repeat: repeat;
                background-position: 0 0;
                background-size:300px 300px;
            }
            /*无水印*/
            .watermark.water-no{
                display: none !important;
            }
    
            /* 调试用 */
            body{
                padding: 10px;
                padding-bottom: 100%;/*如果不加,那么调试的哪些div全是absolute,fixed布局,会导致body本身并没有撑开高度,所以转pdf后会看不到水印*/
            }
            .test-canvas{
                position: absolute;
                left: 430px;
                top: 10px;
            }
    
            /* 计算用 */
            .test-fli{
                position: absolute;
                left: 150px;
                top: 150px;
            }
            .test-con{
                position: absolute;
                left: 10px;
                top:  10px;
                width: 400px;
                height: 400px;
                outline: 1px solid #f00;
            }
            .con1,
            .con2,
            .con3{
                outline: 1px solid #0f0;
                width: 278px;
                height: 110px;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .con1{
                position: absolute;
                left: 0;
                top: 0;
            }
            .con2{
                outline: 1px dashed #0f0;
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%,-50%);
            }
            .con3{
                outline: 1px dashed #00f;
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%,-50%) rotate(-45deg);
            }
        </style>
        <!-- <script src="download2.js"></script> -->
    </head>
    <body>
        <!--水印-->
        <div class="watermark"></div>
        <div class="test-fli">
            <div class="test-canvas" style="left: 10px;">
                <canvas id="myCanvas" width="400" height="400" style="outline:1px solid #f00;"></canvas>
            </div>
            <!-- 对比参照用 -->
            <div class="test-con">
                <div class="con1">原位置(canvas画布文字内容的宽高)</div>
                <div class="con2">居中</div>
                <div class="con3" style="font-size: 20px;line-height: 30px;text-align: center;"></div>
            </div>
        </div>
    <script>
        //初始化加载
        $(function () {
            function canvasToBase64(text,opt){
                //水印内容
                var txt = text;//多行文本,用逗号(,)分割。
                if(!text) return false;
                var txtArr = txt.split(',');
                if(!opt){
                    opt = {};
                }
                //水印配置:字体,字号,是否加粗,文本倾斜角度,文本颜色,水印图的宽高(必须大于文本宽高)
                var fontSize = opt.fontSize || 20;//单位:px,单行文本的字号
                var fontSizeArr = opt.fontSizeArr ? opt.fontSizeArr : [];//单位:px,多行文本的字号
                var lineHeight = opt.lineHeight ? opt.lineHeight : Math.floor(fontSize*1.5);//行高,默认为fontSize字号的1.5倍行高
                var fontFamily = opt.fontFamily || '宋体';//字体,默认宋体
                var fontWeight = opt.fontWeight || 'bold';//是否加粗,默认加粗
                var angle = opt.angle || -45;//文本倾斜角度,默认-45deg
                var fontColor = opt.fontColor || '#d9d9d9';//文本颜色,默认'#d9d9d9'
                var width = opt.width || 200;//画布canvas宽度,单位px,默认200
                var height = opt.height || 200;//画布canvas高度,单位px,默认200
                
                var txtHeight = lineHeight*(txtArr.length)- (lineHeight-fontSize);//文字高度,因为文字垂直方向是top,高度需要减掉最后一行文本的多余行间距:lineHeight-fontSize
                // var canvas = document.getElementById("myCanvas");//本地调试效果用
                var canvas = document.createElement('canvas');
                canvas.width = width;
                canvas.height = height;
                var context = canvas.getContext("2d");
                // 设置字体
                context.font = fontWeight+' '+fontSize+'px '+fontFamily;//比如:"bold 20px 宋体"
                // 设置水平对齐方式
                context.textAlign = 'left';//left,center,right
                // 设置垂直对齐方式
                context.textBaseline = 'top';//top,bottom,middle
    
                //不旋转,参考用
                // var angle = -45;
                var strWidth = context.measureText(txt).width;
                var strWidthArr = [];
                txtArr.forEach(function(txt, index){
                    var tempW = Math.ceil(context.measureText(txt).width);//向上取整,保证无小数
                    strWidthArr.push(tempW);
                });
                console.log('文字块:',strWidthArr);
                strWidth = Math.max.apply(null,strWidthArr);
                console.log("文字块宽高:"+strWidth+','+txtHeight);
                context.save();
                var tx = (canvas.width - strWidth)/2;
                var ty = (canvas.height - txtHeight)/2;//字号等于行高 
        
                //中心位置旋转
                context.save();
                //p0 画布起始点(0,0),p1 canvas画布中心点(canvas.width/2, canvas.height/2),p2 文本块最终位置的左上角那个店(x2,y2)未知的需计算
                var p1p2 = Math.sqrt(Math.pow(strWidth/2,2)+Math.pow(txtHeight/2,2));//文本块左上角,中心点连线长度
                var p1p2Angle = (Math.atan(strWidth/txtHeight)*180/Math.PI-(90-Math.abs(angle)))*Math.PI/180;//文本块左上角,中心点连线和水平轴x的角度
                console.log('文本块left-center连线: length:'+p1p2+',angle(PI):'+p1p2Angle);
                tx = (canvas.width/2)-Math.cos(p1p2Angle)*p1p2;
                ty = (canvas.height/2)+Math.sin(p1p2Angle)*p1p2;
                console.log('p2:('+tx+','+ty+')');
                // ty = 334;
                context.translate(tx, ty);
                context.rotate(angle * Math.PI / 180);//先移动translate,再旋转rotate,就是以文本原点为基点,如果先旋转再移动,就是以画布canvas原点为基点
                context.fillStyle = fontColor;
                var y = 0;
                var x = 0;
                txtArr.forEach(function(txt, index){
                    if(fontSizeArr.length==txtArr.length){
                        //如果每行文本的字号不一样
                        var tempFontSize = fontSizeArr[index];
                        context.font = fontWeight+' '+tempFontSize+'px '+fontFamily;//比如:"bold 20px 宋体"
                    }
                    x = (strWidth - strWidthArr[index])/2;
                    context.fillText(txt, x, y + lineHeight * index);
                });
    
                // context.fillText(txt, 0, 0);//单行文字
                context.restore(); 
                
    
                // 生成图片信息
                var dataUrl = canvas.toDataURL('image/png');
                return dataUrl;
            }
            // var photoUrl = canvasToBase64('存量房网上交易平台,合同编号:预201911260001,2022/10/13 11:01:02');
            //调试文本:合同草稿,XT20220708151515
            //多行文本:逗号(,)分割,比如:'存量房网上交易平台,合同编号:预201911260001,2022/10/13 11:01:02'
            var photoUrl = canvasToBase64('阜阳市,新建商品房交易网上交易平台,合同编号:FY2022335646,2022/10/13 11:01:02',{
                width: 400,
                height: 400,
                fontSize: 20,
                // angle: -30,
                // fontSizeArr: [18,20,18],//多行文本,每行文字字号不一样时配置
                // lineHeight: 30,//默认为字号的1.5倍行高
                // fontColor: '#f00',
            });
            // console.log('文字转图片:',photoUrl);
            $('.watermark').attr('style','display:block;background-image:url('+photoUrl+');background-size:400px 400px');
        });
    
    
    </script>
    </body>
    </html>
    
    
    • 效果图:

      效果图1.jpg
    • 缺点: 暂无。

    参考

    相关文章

      网友评论

        本文标题:合同模板动态生成水印的优化历程

        本文链接:https://www.haomeiwen.com/subject/oyxznrtx.html