给思源的图片导出增加高级水印功能

原理不复杂,但是说起来可能比较啰嗦。

图片背景

首先我们需要知道,CSS 可以为一个元素设置图片背景,例如下面这段代码:

<div style="background-image: url(/assets/ChiliPowder-20240606233038-qme6rlm.png);height:400px">/assets/ChiliPowder-20240606233038-qme6rlm.png</div>

上面这段代码定义了一个带有图片背景的 div 元素,很容易想到,如果我们有一张水印图片,就可以在我们要添加水印的元素后面加上这个背景。

例如下面这样:

<div style="background-image: url(/assets/1719628922704-20240629104229-vk3477u.jpg);background-size:200px;height:400px;font-size:xxx-large;color:pink">如果你扫描下面二维码就会发现它是我们的支付宝收款码</div>

但是这样只能使用现成的图片作为背景,那么有什么办法能够快速生成一个图片背景呢?

svg 的 foreignElement

SVG (Scalable Vector Graphics) 提供了丰富的图形绘制功能,可以用来生成各种复杂的图形和图像。使用 SVG 的 foreignObject 元素,我们可以在 SVG 图形中嵌入 HTML 或 XHTML 内容,从而实现复杂的图片背景效果。

下面是一个简单的示例,演示如何使用 SVG 的 foreignObject 元素来生成带有文本内容的图片背景:

<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="100%" height="100%">
    <div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px; background: lightgrey;">
      <p>这是一个嵌入的HTML段落。</p>
    </div>
  </foreignObject>
</svg>

在这个示例中,我们创建了一个 400x200 像素的 SVG 画布,并在其中嵌入了一个带有背景颜色和文本内容的 HTML div 元素。这种方法允许我们使用 CSS 来控制嵌入内容的样式,从而实现丰富的图片背景效果。

动态生成背景图片

使用 SVG 和 foreignObject 元素,我们还可以动态生成背景图片。例如,我们可以使用 JavaScript 来创建带有自定义文本内容的 SVG 图像,并将其作为背景应用到页面元素中。下面是一个简单的例子:




<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Dynamic SVG Background</title>
<style>
  #watermark {
    width: 100%;
    height: 200px;
    background-size: cover;
    background-repeat: no-repeat;
  }
</style><div id="watermark">这里是一些文本内容。</div><script>
  function generateSVGBackground(text) {
    const svg = `
      <svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
        <foreignObject width="100%" height="100%">
          <div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px; background: lightgrey;">
            <p>${text}</p>
          </div>
        </foreignObject>
      </svg>
    `;
    return `data:image/svg+xml;base64,${btoa(svg)}`;
  }

  const backgroundImage = generateSVGBackground('这是一个动态生成的水印文本');
  document.getElementById('watermark').style.backgroundImage = `url(${backgroundImage})`;
</script>



在这个示例中,我们定义了一个 generateSVGBackground 函数,该函数接受一个文本参数,并返回一个包含该文本内容的 SVG 图像的 Base64 编码字符串。然后,我们将生成的背景图片应用到 div 元素上,最终实现动态生成背景图片的效果。

实现导出时的复杂水印

只要动态地将这张背景图片添加到思源的图片导出界面里面,就可以实现复杂水印了.

下面这段代码利用 SACPublishHelpper 插件实现了一个新的特殊代码块,当界面加载时,使用语言名为 siyuan-export-watermark 的代码块将会为导出图片功能添加水印:

{
                name: "siyuan-export-watermark",
                baseLang: "html",
                options: {
                    onregistered: (element, container, content) => {
                 
                        加载代码块内容("siyuan-export-watermark", async (block) => {
                            const svgContent = `
                            <svg xmlns="http://www.w3.org/2000/svg"  width="200" height="200" viewBox="0 0 200 200">
                                <foreignObject width="180" height="180" >
                                    <div xmlns="http://www.w3.org/1999/xhtml" style="font-size:20px; color: gray;">
                                        ${block.content}
                                    </div>
                                </foreignObject>
                            </svg>
                        `;
                            const encodedSVG = encodeURIComponent(svgContent);
                            const dataURL = `url("data:image/svg+xml;utf8,${encodedSVG}")`;
                            const css = `.export-img>.protyle-wysiwyg.protyle-wysiwyg--attr::before{
                                content:"";
                                background-image:${dataURL};
                                background-repeat: repeat;
                                background-size:25%;
                                width:100%;
                                height:100%;
                                position:absolute;
                                z-index:1000
                            }`
                            const style =document.createElement('style')
                            style.textContent=css
                            document.head.appendChild(style)
                        })
                    }
                }
            }

这个发布站点的水印是这样定义的,你可以尝试导出图片来查看它的效果:

<div style="color: pink; opacity: 0.2; font-size: 20px; font-family: Arial;text-align:center">publish.ccsjhn.com 椽承设计</div>

完整效果可以参考 www.ccsjhn.com/?id=20240628023554-snpa1ac

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    22337 引用 • 89380 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...