当前位置: 首页 > news >正文

制作可以赚钱的网站网站页面设计如何收费

制作可以赚钱的网站,网站页面设计如何收费,中国教学网站,截止今天全世界新冠病人多少❝ 注:当前使用的是 ol 9.2.4 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 在WebGIS系统开发中,有时候会遇到只需要展示某一图层特殊区域的需求,通常情况下需要单独发一个地图服务,但为了简…

注:当前使用的是 ol 9.2.4 版本,天地图使用的key请到天地图官网申请,并替换为自己的key

WebGIS系统开发中,有时候会遇到只需要展示某一图层特殊区域的需求,通常情况下需要单独发一个地图服务,但为了简化操作,可以利用OpenLayers进行图层遮罩与裁剪处理。

1. 图层遮罩

图层遮罩即为图层加上遮罩层,单独留出展示区域。结合canvas,通过上下文属性globalCompositeOperation和绘制方法可以方便的设置遮罩层。

1.1. 创建canvas元素

创建canvas元素,并将其添加到地图视图作为子元素,设置position为绝对定位,宽高与父元素相等,然后设置显示层级在父元素之上。

const { offsetWidth, offsetHeight } = map.getViewport()
overCanvas = document.createElement('canvas');
overCanvas.width = offsetWidth;
overCanvas.height = offsetHeight;
overCanvas.style.position = 'absolute';
overCanvas.style.top = '0';
overCanvas.style.left = '0';
overCanvas.style.zIndex = '99';
const ctx = overCanvas.getContext('2d');
map.getViewport().appendChild(overCanvas);

1.2. 设置遮罩层样式

fillStyle为填充色,strokeStyle为边线色,lineWidth为边线宽度。

const fillStyle = 'rgba(255,255,255,1)'
const strokeStyle = 'red'
const lineWidth = 3ctx.fillStyle = fillStyle;
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;

1.3. 绘制遮罩层

清除画布: 在绘制遮罩层之前需要使用clearRect方法清除画布。clearRect方法会将从左上角(0,0)开始,宽高为地图大小的矩形区域设置为透明黑色(rgb(0 0 0 / 0%))。

坐标转换: 使用map.getPixelFromCoordinate将地理坐标转换为屏幕坐标,对于地理坐标系,可以直接转换,若为投影坐标系,需要使用ol.proj.fromLonLat将其转为投影坐标,再转换为屏幕坐标。

绘制遮罩层:调用beginPath开始绘制路径,moveTo表示起点,lineTo表示绘制路径,绘制完成后使用closePath关闭路径,然后调用fill完成填充,第一个形状绘制完成,简称s1。然后使用rect绘制矩形,调用fill进行填充,第二个形状绘制完成,简称s2。在s1s2之间设置globalCompositeOperation属性为source-outglobalCompositeOperatio = 'source-out'表示新形状为原来的形状s1和后面的形状s2不相交的部分。

绘制显示范围线: 使用stroke方法进行路径绘制。globalCompositeOperatio = 'source-over'表示新形状位于旧形状之上,显示层级更高。

// 清除画布
ctx.clearRect(0, 0, overCanvas.width, overCanvas.height)
const ynJSON = YNGeoJSON.features[0].geometry.coordinates[0][0]
const coords = ynJSON.map(coord => {// return map.getPixelFromCoordinate(ol.proj.fromLonLat(coord))return map.getPixelFromCoordinate(coord)
})// 绘制显示区域
ctx.beginPath();
coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])
})
ctx.closePath();
ctx.fill();// 绘制遮罩层
ctx.globalCompositeOperation = 'source-out';
ctx.rect(0, 0, overCanvas.width, overCanvas.height)
ctx.fill();// 绘制路径
ctx.globalCompositeOperation = 'source-over';
ctx.beginPath();
coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])
})
ctx.closePath();
ctx.stroke()

方式一:先绘制显示区域,再绘制遮罩层,设置ctx.globalCompositeOperation = 'source-out'

// 绘制显示区域
ctx.beginPath();
coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])
})
ctx.closePath();
ctx.fill();ctx.globalCompositeOperation = 'source-out';// 绘制遮罩层
ctx.rect(0, 0, overCanvas.width, overCanvas.height)
ctx.fill();

方式二:先绘制遮罩层,再绘制显示区域,设置ctx.globalCompositeOperation = 'destination-out'

// 绘制遮罩层
ctx.rect(0, 0, canvas.width, canvas.height)
ctx.fill();ctx.globalCompositeOperation = 'destination-out';// 绘制显示区域
ctx.beginPath();
coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])
})
ctx.closePath();
ctx.fill();

方式二:先绘制遮罩层,再绘制显示区域,设置ctx.globalCompositeOperation = 'xor'

// 绘制遮罩层
ctx.fillRect(0, 0, canvas.width, canvas.height)ctx.globalCompositeOperation = "xor";// 绘制显示区域
ctx.beginPath();
coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])
})
ctx.closePath()
ctx.fill();

1.4. 取消遮罩

移除添加的遮罩元素即可取消遮罩。

/*** 取消遮罩*/
function cancelOverlay(overCanvas) {map.getViewport().removeChild(overCanvas);
}

2. 图层裁剪

2.1. 创建裁剪要素

在进行图层裁剪之前需要创建裁剪要素,可以通过GeoJSON数据构建裁剪要素区域。

const coords = YNGeoJSON.features[0].geometry.coordinates[0]
const clipFeature = new ol.Feature({geometry: new ol.geom.Polygon(coords),
})

2.2. 开启裁剪

创建图层裁剪方法,传递待裁剪图层和裁剪要素参数。监听裁剪图层渲染前和渲染后事件,在图层渲染前进行裁剪,渲染完成后恢复画布,并设置图层显示范围为裁剪区域。

/*** 创建裁剪* @param {ol.layer} clipLayer 需要裁剪的图层* @param {ol.feature} clipFeature 裁剪区域*/ 
function createClipByLayer(clipLayer, clipFeature) {// 监听图层渲染前事件,进行裁剪操作clipLayer.on("prerender", prerenderEvt)// 监听图层渲染后事件,进行画布恢复clipLayer.on("postrender", postrenderEvt)// 设置裁剪范围clipLayer.setExtent(clipFeature.getGeometry().getExtent())
}

**prerenderEvt** 图层渲染前处理事件

function prerenderEvt(event) {const vectorContext = ol.render.getVectorContext(event);event.context.globalCompositeOperation = 'source-over';const ctx = event.context;// 保存裁剪前画布状态ctx.save();// 绘制裁剪区域vectorContext.drawFeature(clipFeature, new ol.style.Style({stroke: new ol.style.Stroke({color: "red",width: 5,}),fill: new ol.style.Fill({color: "rgba(0, 0, 255, 0.25)",})}));ctx.clip();
}

**postrenderEvt** 图层渲染后处理事件

function postrenderEvt(event) {let ctx = event.context;// 恢复裁剪前画布状态ctx.restore();
}

2.3. 取消裁剪

取消裁剪操作前先移除裁剪图层,然后再将其添加到地图中,并取消地图渲染监听事件,最后设置地图全幅范围显示。

/*** 取消裁剪* @param {ol.layer} clipLayer 需要裁剪的图层* @param {ol.layer} fullExtentLayer 地图全图范围图层*/
function cancelClip(clipLayer,fullExtentLayer) {map.removeLayer(clipLayer)map.addLayer(clipLayer)// 设置图层显示层级clipLayer.setZIndex(-1)// 取消图层事件监听clipLayer.un("prerender", prerenderEvt)clipLayer.un("postrender", postrenderEvt)// 设置图层全幅显示clipLayer.setExtent(fullExtentLayer.getExtent())
}

3. 不成功的例子

在下面的代码中,我想通过监听地图事件precomposepostcompose来完成裁剪操作,这样就不用针对每个图层进行裁剪了。但是运行发现并没有达到理想的效果,有两个问题,一是坐标计算不对,应该是地理坐标转换为屏幕坐标不准确;二是裁剪后图层并没有只显示裁剪区域,随着地图放大、缩小或者拖动,其他区域也会显示出来。我暂时也没有想到更好的解决办法,等着以后再探究吧,也希望有想法的小伙伴可以指正一下。

/*** 开启裁剪*/
function startClip() {map.on("precompose", function (event) {const canvas = document.querySelector("canvas");const ctx = canvas.getContext("2d");ctx.save();ctx.reset()ctx.beginPath();const ynJSON = YNGeoJSON.features[0].geometry.coordinates[0][0]// ctx.rect(0, 0, canvas.width, canvas.height);const coords = ynJSON.map(coord => {return map.getPixelFromCoordinate(ol.proj.fromLonLat(coord,map.getView().getProjection()))})coords.forEach((coord, index) => {// const y = ol.render.getRenderPixel(event,coord[1])index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])})ctx.closePathctx.clip();ctx.globalCompositeOperation = 'source-over';ctx.beginPath();coords.forEach((coord, index) => {index === 0 ? ctx.moveTo(coord[0], coord[1]) : ctx.lineTo(coord[0], coord[1])})ctx.closePath();ctx.stroke()});map.on("postcompose", function (event) {const canvas = document.querySelector("canvas");const ctx = canvas.getContext("2d");ctx.restore()})
}

4. canvas小知识

现代前端二维地图库,区别于三维地图WebGL模式,基本上都是利用canvas进行渲染,所以了解一下canvas相关知识是有必要的。在使用canvas对象时,要进行其他操作前,必须要先获取canvas上下文对象,即ctx``const ctx = canvas.getContext("2d")下面介绍一些绘制方法和属性

方法名称作用
clearRect(x, y, width, height)创建从左上角(x,y)开始,宽高为widthheight的黑色透明矩形区域
fill()根据fillStyle填充绘制区域
stroke()根据给定strokeStyle绘制边线
rect(x, y, width, height)绘制从左上角(x,y)开始,宽高为widthheight的矩形,需要结合fill()stroke使用
fillRect(x, y, width, height)根据fillStyle绘制从左上角(x,y)开始,宽高为widthheight的矩形
moveTo(x, y)根据坐标(x,y)为起点开始路径绘制
lineTo(x, y)绘制从上一个点到给定坐标(x,y)的直线,结合fill()stroke将路径添加到canvas
clip()裁剪给定区域。由于裁剪的不可恢复性,在裁剪开始前需要使用save保存状态,裁剪完成后使用restore进行恢复
reset()重置绘制路径以及样式等
save()保存绘制前的状态,如fillStyle
restore()恢复绘制前的状态,如fillStyle
strokeStyle设置边线样式,如strokeStyle="red"或者strokeStyle="#ddd"或者strokeStyle="(255,255,255,0.25)"
fillStyle设置填充样式,如fillStyle="red"或者fillStyle="#ddd"或者fillStyle="(255,255,255,0.25)"

全局合成属性globalCompositeOperation我将现有画布内容简称为旧形状,新绘制对象为新形状。

属性值作用
"source-over"默认设置,绘制的形状在旧形状之
"source-in"形状在新形状和目标画布重叠的地方绘制。其他透明。
"source-out"新形状在新形状与旧形状没有重叠的地方进行绘制(绘制非重叠区域)
"source-atop"新形状仅绘制与旧形状重叠的区域(绘制重叠区域)
"destination-over"绘制的形状在旧形状之
"destination-in"形状在新形状和目标画布重叠的地方绘制。其他透明。
"destination-out"绘制形状与新形状的非重叠区域
"destination-atop"现有画布仅保留与新形状重叠的区域。新形状绘制在画布内容后面。
"copy"只显示形状
"xor"新旧形状相交的区域为透明,其他区域正常显示

5. 参考知识

牛老师:https://mp.weixin.qq.com/s/Jv5zhxG1wAoJUzDBe8XsrAcanvas:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing

OpenLayers:https://openlayers.org/en/v9.2.4/examples/layer-clipping-vector.html

http://www.yayakq.cn/news/996736/

相关文章:

  • 苏州h5建站桂林网络推广外包
  • 杭州专门做网站微信网站合同
  • iis网站连接数网站文章更新注意什么
  • 婚纱照网站制作最近中国新闻热点大事件
  • 网站域名证书怎么获取专业网络推广平台
  • 网站建设杭州最便宜有专门教做儿童美食的网站吗
  • 自己学建网站手机上使用wordpress
  • 网站开发程序设计中国最大型网站
  • 旅游网站制作内容县城做网站的多么
  • 江苏seo推广网站建设广州seo优化外包服务
  • 网站开发的基本流程二级域名怎么解析
  • 北京新增死亡病例详情网站seo优化建议
  • 二级网站建设 管理思路试玩平台网站怎么做
  • 中天建设招标网站html 类似淘宝购物网站上加载时获取属性并可多选过滤 代码
  • 案例模板我的网站百度指数官网数据
  • 太原房产网站建设天猫与京东的网站建设管理
  • 8090在线观看免费观看优化百度百科
  • 网站设计宽度尺寸万国手表网站
  • 网站建设佰金手指科杰二六开发公司送物业费的协议
  • 苏州网站建设的公司哪家好网站建设制作流程
  • 做视频网站要什么主机dedecms 网站安装教程
  • 辛集做网站公司可以做任务的网站有哪些
  • 河北做网站的业务员用什么软件找客户
  • 肇庆网站制作设计做网站产品介绍
  • 做网站不用服务器吗全国论坛网站建设
  • 婚庆网站建设公司做app 的模板下载网站有哪些
  • 上海网站制作优化网站的站点建设
  • 网站托管wordpress的网站怎么保存
  • 可以做图接单的网站优跃达官网网站建设项目
  • 塑胶材料东莞网站建设企业网站建设方案平台