Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React

  • Vue

  • JavaScript文章

  • 学习笔记

  • openlayers

    • Openlayers用图片填充面
      • Openlayers用图片填充线
      • openlayers处理大量Overlay渲染问题
      • openlayers的比例尺
      • openlayers水印
      • openlayer实现矢量图层点击高亮效果
      • openlayers实现自定义路径
      • Openlayers加载渲染矢量切片
      • openlayers实现角度测量
      • openlayers实现长度测量
      • openlayers实现面积测量
      • Openlayers实现方位角测量
      • Openlayers中的动画
      • Openlayers的多边形高级交互
      • Openlayers地图底图换色
      • Openlayers种的默认交互事件
      • Openlayers默认键盘交互实现
      • 源码分析之Openlayers中默认键盘事件触发机制
      • 源码分析之Openlayers中的Collection类
    • threejs

    • MapboxGL

    • 工具

    • 源码合集

    • 前端
    • openlayers
    东流
    2024-08-07
    目录

    Openlayers用图片填充面

    # 概述

    我们知道Openlayers通常设置feature要素的方式主要是通过ol.style.stroke描边和ol.style.fill填充,这对比较简单的样式设置十分有效。如果要设置feature的图标,还可以通过ol.style.Icon加载外部图片资源,但是如果要设置面的填充,就需要稍微复杂的设置。

    # 效果

    # 解决方案

    # colorlike

    Openlayers中定义了colorlike类型, 通过ol.colorlike可以加载图片资源,返回的是一个CanvasPattern,而ol.style.fill的color属性可以接受这个值,从而实现图片的填充。 colorlike提供一个方法asColorLike,参数可以是一个图片,返回一个 color,其类型为Color|ColorLike|Patttern

    # CanvasPattern

    但是在开发中,用到比较多的是CanvasPattern,它是canvas中的类型,在 MDN 中的描述如下

    CanvasPattern接口表示一个不透明对象,描述了一个基于图像、画布或视频的模板,该模板通过CanvasRenderContext2D.createPattern方法创建。 它们可用作fillStyle或strokeStyle

    CanvasRenderContext2D就是通过canvas.getContext("2d")获取的canvas 2d 的上下文环境

    但是如果我们需要动态改变填充图片的透明度,单纯依靠CanvasPattern是无法实现,因为如上的定义中已经提及它是表示一个不透明对象,如果外部资源图片是一个透明图片呢,那样也只能保证初始是透明,而无法动态修改。这时就需要用到canvas中的 API 了。

    # canvas的魔力

    先看看如下示例

    export const getImagePattern = (imgUrl, opacity = 1) => {
      return new Promise((resolve, reject) => {
        var img = new Image();
        img.src = imgUrl;
        img.onload = function () {
          var cnv = document.createElement("canvas");
          var ctx = cnv.getContext("2d");
          cnv.width = img.width;
          cnv.height = img.height;
          ctx.drawImage(img, 0, 0);
    
          var imageData = ctx.getImageData(0, 0, cnv.width, cnv.height);
          var data = imageData.data;
    
          for (var i = 3; i < data.length; i += 4) {
            data[i] = opacity * 255;
          }
          ctx.putImageData(imageData, 0, 0);
          var pattern = ctx.createPattern(cnv, "repeat");
          resolve(pattern);
        };
        img.onerror = function (error) {
          reject(error);
        };
      });
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    示例中定义一个获取图片Pattern的方法,返回的是一个Promise对象,接受两个参数

    • img:资源图片
    • opacity:透明度 (0~1)

    在图片加载成功后,创建一个canvas画布,调用drawImage方法将图片渲染到画布上,再通过getImageData方法拿到图片数据,改变每个像素的透明度,再次渲染到画布上,最后调用createPattern方法创建pattern

    # getImageData方法

    getImageData方法可以实现对图像的像素操作,其语法:ctx.getImageData(x,y,w,h)

    参数

    x:被提取图像矩形区域的左上角 x 坐标 y:被提取图像矩形区域的左上角 x 坐标 w:被提取图像矩形区域的宽度 h:被提取图像矩形区域的高度

    补充一点:canvas画布的原点坐标:(0,0)位于画布的左上角

    返回值

    getImageData会返回一个ImageData对象,它包含canvas给定的也是被提取图像的矩形区域的数据。该对象的height和width分别对应参数h和w,而示例中用到的imageData.data则是一个一维数组,包含以RGBA顺序的数据,大小为 0 —— 255 的整数表示

    示例中的 for 循环就是处理RGBA中A即alpha:透明度

    所以这会引发一个新的问题,如果图片很大,这种遍历的操作会带来性能的问题

    # putImageData方法

    putImageData顾名思义就是将ImageData对象绘制到画布中,示例中只写了必传的参数,其语法为

    putImageData(imageData, dx, dy);
    putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
    
    1
    2

    参数

    imageData:上面提到的ImageData对象 dx和dy就是要绘制到canvas的起始位置 dirtyX和dirtyY对应ImageData中的左上角的坐标,默认均为 0 dirtyWidth:要绘制的矩形的宽度,默认为imageData的宽度 dirtyHeight:要绘制的矩形的宽度,默认为imageData的高度

    # 调用

    调用getImagePattern方法时,动态改变参数opacity获取到pattern赋值就可以实现Openlayers的fetaure填充图像的透明度改变

    const pattern = await getImagePattern(img, opacity / 100);
    newStyle = new Style({
      stroke: new Stroke({
        color: color,
        width: width,
      }),
      fill: new Fill({
        color: pattern,
      }),
    });
    fetaure.setStyle(newStyle);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    编辑 (opens new window)
    #webgis#canvas
    上次更新: 2024/12/03, 14:43:37
    JSzip插件介绍
    Openlayers用图片填充线

    ← JSzip插件介绍 Openlayers用图片填充线→

    最近更新
    01
    GeoJSON
    05-08
    02
    Circle
    04-15
    03
    CircleMarker
    04-15
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式