【问题标题】:Create a rough sketchy border around images or text with different sizes?在不同大小的图像或文本周围创建粗略的粗略边框?
【发布时间】:2022-10-25 15:13:13
【问题描述】:

所以我需要一些文本、图像和其他元素,以便在它们周围有一种粗略的手绘边框。例如,这里是我使用 rough.js 库创建的。

example rough border image

我对如何解决这个问题有多种想法。我不知道哪一个可能是最好的,或者是否还有其他更好的选择。

要求是单个图像周围的粗略边框,画廊周围的多个图像,标题或带有文本图像和按钮的整个博客元素。当然,所有这些都是响应式的。

到目前为止,我的选择如下:

香草 CSS

Vanilla css 方法是创建一个粗略的边框,如下所示:https://codemyui.com/hand-drawn-border-buttons-css/

这并不真正满足要求,因为它并不真正接近所需的最终产品。我添加的示例有多个边界线,而香草 css 边界是不可能的。

SVG

另一种选择是将边框作为 SVG 元素添加到代码中,然后将它们放在图像上方。这似乎不是很好,因为对于一个人来说,我只想在元素上设置一个类来实现这个边框,并且仍然保留将前后元素用于其他目的的可能性。

另外我想这会因为不同的屏幕尺寸而改变元素的尺寸和纵横比而变得困难,类似于边框图像可能不起作用的方式。

粗糙的.js

Rough.js 是一个很棒的库,体积小,效果好。这个库的问题是随机性。对于整个页面的特定元素,边框应该具有独特的外观。似乎没有停用所述随机性的选项(我猜是有道理的)。

另外我宁愿不使用任何库。

帆布

通过 JS 添加画布并在图像顶部创建绘制边框似乎确实有效。这里的问题是,页面上的许多元素需要重新创建为画布。我不知道这是否真的会影响性能,但我认为它会在将这么多元素作为画布时产生许多其他困难。

我对画布的了解也很有限。

创建 SVG

我一直在研究的另一个选择是以编程方式创建 svg 并将它们添加到图像中。到目前为止,这似乎在使用 Rough.js 创建 svg 时有效。我不知道在 vanilla 或 jquery 中创建它会有多复杂。以及那将是多么实用。还有如何在不使用任何伪元素的情况下将其添加到图像/文本元素中。

创建一个 Paintworklet

一个很好的解决方案是使用paint worklet 和registerpaint。然后通过边框图像调用它。这种方法我真的很喜欢。这里的问题是浏览器功能,因为包括 firefox 在内的许多浏览器不支持 registerPaint。如果有办法使用这个跨浏览器,我真的很喜欢这个解决方案。


所以到目前为止,这些是我的选择。对于我的方案的最佳选择和/或我还没有考虑过更好的选择和解决方案,我真的很感激一些建设性的批评。

PS:我没有添加任何代码,因为它并不重要。它应该独立于底层代码工作。

【问题讨论】:

    标签: javascript html jquery css


    【解决方案1】:

    svg 过滤器 <feTurbulence><feDisplacementMap>

    您可以尝试Daniel Jones (How to make rough edges with CSS and SVGs) 描述的这种方法

    示例1:使用随机<feTurbulance>

    body {
      font-size: 5vw;
    }
    
    .resize {
      position: relative;
      resize: both;
      overflow: auto;
      padding: 0.3em;
    }
    
    .frame {
      padding: 0.3em;
      margin-bottom: 0.5em;
    }
    
    .roughtEdges-after:after,
    .frame-border {
      border: 10px solid #000;
    }
    
    .roughtEdges-after {
      position: relative;
    }
    
    .roughtEdges-after:after {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
    
    .roughtEdges-after:after,
    .roughtEdges {
      filter: url(#roughtEdges);
    }
    <h3>Resize frame</h3>
    <div class="resize">
      <div class="frame roughtEdges-after">
        <span class="nofilter">
                Filter applied on border
            </span>
      </div>
      <div class="frame frame-border roughtEdges">
        Filter applied on border and text
      </div>
    </div>
    
    <!-- SVG filters -->
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0" width="0">
        <defs>
            <filter id="roughtEdges">
            <!-- you could also use 'fractalNoise' type option for a different result --> 
                <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence" />
                <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="5" xChannelSelector="R" yChannelSelector="G" />
            </filter>
        </defs>
    </svg>

    优点:

    • 可通过 css filterproperty 轻松重用
    • 反应灵敏

    注意事项:

    • 随机噪声

    示例 2:&lt;feImage&gt; 产生的噪声

    描述于Codrops: SVG Filter Effects: Conforming Text to Surface Texture with feDisplacementMap

    body {
      font-size: 5em;
    }
    
    .resize {
      position: relative;
      resize: both;
      overflow: auto;
      padding: 0.3em;
    }
    
    .frame {
      padding: 0.3em;
      margin-bottom: 0.5em;
    }
    
    .frame-border {
      border: 10px solid #000;
    }
    
    .roughtEdges-after {
      position: relative;
    }
    .roughtEdges-after:after {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      border: 10px solid #000;
    }
    
    .roughtEdges-after:after,
    .roughtEdges {
      filter: url(#roughtEdges);
    }
    <!--
    <img src="https://i.imgur.com/nAG8WN9.jpeg" alt="">
    -->
    <div class="resize">
        <div class="frame roughtEdges-after">
            <span class="nofilter">
                Filter applied on border
            </span>
        </div>
        <div class="frame frame-border roughtEdges">
            Filter applied on border and text
        </div>
    </div>
    
    <!-- SVG filters -->
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%">
        <filter id="roughtEdges" x="-50%" y="-50%" width="200%" height="200%">
            <feImage preserveAspectRatio="none" href="data:image/jpeg;base64,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" />
            <feDisplacementMap in="SourceGraphic" scale="4" xChannelSelector="R" yChannelSelector="R" />
        </filter>
    </svg>

    优势:

    • 较少的随机性,因为噪声是由静态图像定义的

    注意事项:

    • ...仍然有很多随机性,由于浏览器特定的渲染偏差

    因此,不可否认,所描述的方法都不是完美的。
    但是您也许能够找到适合您需求的组合。

    【讨论】:

    • 嘿,非常感谢您的意见。我尝试了这个并玩了一段时间,我认为它没有给我想要的结果。开始相信不编写深度画布算法是不可能的。
    【解决方案2】:

    不确定这是否是您需要的。随机性可以通过种子参数来控制。

    const canvas = document.getElementById('canvas')
    canvas.width = 400
    canvas.height = 400
    
    const rc = rough.canvas(canvas)
    
    // random rects
    rc.rectangle(10, 10, 100, 100, { roughness: 2.8 })
    rc.rectangle(130, 10, 100, 100, { roughness: 2.8 })
    rc.rectangle(250, 10, 100, 100, { roughness: 2.8 })
    
    // determined rects, with seed value for each call
    rc.rectangle(10, 130, 100, 100, { seed: 3, roughness: 2.8 })
    rc.rectangle(130, 130, 100, 100, { seed: 3, roughness: 2.8 })
    rc.rectangle(250, 130, 100, 100, { seed: 3, roughness: 2.8 })
    <canvas id=canvas></canvas>
    <script crossorigin="anonymous" src="https://unpkg.com/roughjs@latest/bundled/rough.js"></script>

    rough-paint 可以是一个解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      • 2020-07-16
      • 2017-12-18
      相关资源
      最近更新 更多