阅读 3
^ 关注我,带你一起学GIS ^
注:当前使用的是 ol [9.2.4] 版本,天地图使用的
key
请到天地图官网申请,并替换为自己的key
前言
❝图形绘制是指在地图上绘制点、线、面、圆、矩形等图形。可以通过鼠标单机绘制,也可以键盘按键配合进行绘制。对于绘制的几何图形可以调整线段和端点样式。
1. 图形绘制
本篇文章主要介绍如何设置几何对象线段样式,对于如何进行图形绘制请参考文章OpenLayers 绘制几何对象
2. 创建线段样式结构
在页面中创建线段样式结构并添加其CSS
。线段样式可以调整线宽、端点样式、拐点样式、虚线样式以及间隔等。其中端点样式具有三个值:butt
、round
和square
;拐点样式具有三个值:bevel
、 round
和miter
。
.stroke-style {
position: absolute;
padding: 10px;
top: 120px;
left: 100px;
background-color: #c19b03ab;
border-radius: 2.5px;
}
.stroke-line-style {
display: flex;
}
.line-style {
margin-top: 15px;
width: 80%;
}
<div class="stroke-style">
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">端点样式</label>
<div class="layui-input-block">
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="butt" title="butt">
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="round" title="round"
checked>
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="square" title="square">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">拐点样式</label>
<div class="layui-input-block">
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="bevel" title="bevel">
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="round" title="round"
checked>
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="miter" title="miter">
</div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">线宽(pixel)</label>
<div id="stroke-width-value" class="line-style"></div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">虚线样式</label>
<div id="line-dash-value" class="line-style"></div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">虚线偏移</label>
<div id="line-dash-offset" class="line-style"></div>
</div>
</div>
</div>
3. 重设样式
创建重设样式方法,在该方法中传递样式对象,然后同构解构该对象生成样式对象,在添加新的样式图层前将原来的图层移除。
function setStyle(styleObj) {
const { width, lineCap, lineJoin, lineDash, lineDashOffset } = styleObj
map.removeLayer(vectorLayer)
const style = new ol.style.Style({
fill: new ol.style.Fill({
color: "#9b65ff30"
}),
stroke: new ol.style.Stroke({
color: "yellow",
width: width || lineWidth,
lineCap: lineCap || 'round',
lineJoin: lineJoin || 'round',
lineDash: lineDash || lineDash,
lineDashOffset: lineDashOffset || 0
})
})
vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: style
})
map.addLayer(vectorLayer)
}
4. 监听滑块事件
监听滑块移动事件,在滑块值发生改变时调用重设样式方法。
let lineWidth = 2.5
let lineDash = [30, 40, 50, 60]
layui.use(function () {
const slider = layui.slider;
// 线条宽度
slider.render({
elem: '#stroke-width-value',
value: 5, //初始值
change: function (value) {
lineWidth = value
const styleObj = {
width: lineWidth
}
setStyle(styleObj)
}
});
// 虚线间隔
slider.render({
elem: '#line-dash-value',
value: 0, //初始值
change: function (value) {
lineDash = [value, 40, 50, 60]
const styleObj = {
lineDash: lineDash
}
setStyle(styleObj)
}
});
// 偏移值
slider.render({
elem: '#line-dash-offset',
value: 0, //初始值
change: function (value) {
const styleObj = {
lineDashOffset: value
}
setStyle(styleObj)
}
});
});
5. 监听单选框事件
监听单选框事件,获取单选框点击值然后调用重设样式函数。
layui.use(function () {
const form = layui.form;
const layer = layui.layer;
// radio 事件
form.on('radio(cap-radio-filter)', function (data) {
const elem = data.elem; // 获得 radio 原始 DOM 对象
const checked = elem.checked; // 获得 radio 选中状态
const value = elem.value; // 获得 radio 值
const styleObj = {
lineCap: value
}
setStyle(styleObj)
})
form.on('radio(join-radio-filter)', function (data) {
const elem = data.elem; // 获得 radio 原始 DOM 对象
const checked = elem.checked; // 获得 radio 选中状态
const value = elem.value; // 获得 radio 值
const styleObj = {
lineJoin: value
}
setStyle(styleObj)
})
});
6. 完整代码
其中libs
文件夹下的包需要更换为自己下载的本地包或者引用在线资源。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OpenLayers 线段样式</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../libs/css/ol9.2.4.css">
<link rel="stylesheet" href="../../libs/layui/css/layui.css">
<script src="../../js/config.js"></script>
<script src="../../js/util.js"></script>
<script src="../../libs/js/ol9.2.4.js"></script>
<script src="../../libs/layui/layui.js"></script>
<style>
* {
padding: 0;
margin: 0;
font-size: 14px;
font-family: '微软雅黑';
}
html,
body {
width: 100%;
height: 100%;
}
#map {
position: absolute;
top: 50px;
bottom: 0;
width: 100%;
}
#top-content {
position: absolute;
width: 100%;
height: 50px;
line-height: 50px;
background: linear-gradient(135deg, #ff00cc, #ffcc00, #00ffcc, #ff0066);
color: #fff;
text-align: center;
font-size: 32px;
}
#top-content span {
font-size: 32px;
}
.draw-shape {
position: absolute;
padding: 5px;
top: 60px;
left: 100px;
background-color: #ffcc00ad;
border-radius: 2.5px;
}
.draw-ul {
list-style-type: none;
}
.draw-ul::after {
display: block;
clear: both;
content: "";
}
.draw-li {
float: left;
padding: 5px;
margin: 0 5px;
min-width: 50px;
background-color: azure;
background: #cae4cf82;
transition: background-color 10s ease-in-out 10s;
text-align: center;
border-radius: 2.5px;
transition: color ease-in-out 0.25s;
}
.draw-li:hover {
cursor: pointer;
color: #fff;
filter: brightness(120%);
background: linear-gradient(135deg, #c850c0, #4158d0);
}
.active {
color: #fff;
background: linear-gradient(135deg, #c850c0, #4158d0);
}
.stroke-style {
position: absolute;
padding: 10px;
top: 120px;
left: 100px;
background-color: #c19b03ab;
border-radius: 2.5px;
}
.stroke-line-style {
display: flex;
}
.line-style {
margin-top: 15px;
width: 80%;
}
</style>
</head>
<body>
<div id="top-content">
<span>OpenLayers 线段样式</span>
</div>
<div id="map" title="地图显示"></div>
<div class="draw-shape">
<ul class="draw-ul">
<li class="draw-li" data-type="LineString">线</li>
<li class="draw-li" data-type="Polygon">多边形</li>
<li class="draw-li" data-type="Square">正方形</li>
<li class="draw-li" data-type="Box">矩形</li>
<li class="draw-li" data-type="None">清除</li>
</ul>
</div>
<div class="stroke-style">
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">端点样式</label>
<div class="layui-input-block">
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="butt" title="butt">
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="round" title="round"
checked>
<input type="radio" name="lineCap" lay-filter="cap-radio-filter" value="square" title="square">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">拐点样式</label>
<div class="layui-input-block">
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="bevel" title="bevel">
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="round" title="round"
checked>
<input type="radio" name="lineJoin" lay-filter="join-radio-filter" value="miter" title="miter">
</div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">线宽(pixel)</label>
<div id="stroke-width-value" class="line-style"></div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">虚线样式</label>
<div id="line-dash-value" class="line-style"></div>
</div>
<div class="layui-form-item stroke-line-style">
<label class="layui-form-label">虚线偏移</label>
<div id="line-dash-offset" class="line-style"></div>
</div>
</div>
</div>
</body>
</html>
<script>
//地图投影坐标系
const projection = ol.proj.get('EPSG:3857');
//==============================================================================//
//============================天地图服务参数简单介绍==============================//
//================================vec:矢量图层==================================//
//================================img:影像图层==================================//
//================================cva:注记图层==================================//
//======================其中:_c表示经纬度投影,_w表示球面墨卡托投影================//
//==============================================================================//
const TDTImgLayer = new ol.layer.Tile({
title: "天地图影像图层",
source: new ol.source.XYZ({
url: "http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
attibutions: "天地图影像描述",
crossOrigin: "anoymous",
wrapX: false
})
})
const TDTImgCvaLayer = new ol.layer.Tile({
title: "天地图影像注记图层",
source: new ol.source.XYZ({
url: "http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=" + TDTTOKEN,
attibutions: "天地图注记描述",
crossOrigin: "anoymous",
wrapX: false
})
})
const map = new ol.Map({
target: "map",
loadTilesWhileInteracting: true,
view: new ol.View({
center: [102.845864, 25.421639],
zoom: 5,
worldsWrap: false,
minZoom: 1,
maxZoom: 20,
projection: 'EPSG:4326',
}),
layers: [TDTImgLayer]
})
const style = new ol.style.Style({
fill: new ol.style.Fill({
color: "#9b65ff30"
}),
stroke: new ol.style.Stroke({
color: "yellow",
width: 5,
lineCap: 'round',
lineJoin: 'round',
lineDash: [20, 30, 40, 50],
lineDashOffset: 0
}),
image: new ol.style.Circle({
fill: new ol.style.Fill({
color: "#fff"
}),
radius: 5,
stroke: new ol.style.Stroke({
color: "blue",
width: 1,
})
})
})
const vectorSource = new ol.source.Vector({ wrapX: false })
let vectorLayer = new ol.layer.Vector({
source: vectorSource,
style
})
map.addLayer(vectorLayer)
let drawInteraction = null
/**
* 根据几何类型绘制几何对象
*/
function drawShape(type) {
if (type === "None") {
removeInteraction()
// 清除图形
vectorSource.clear()
removeAllActiveClass(".draw-ul", "active")
return
}
let geometryFunction = null
switch (type) {
case "Square":
type = "Circle"
geometryFunction = ol.interaction.Draw.createRegularPolygon(4)
break
case "Box":
type = "Circle"
geometryFunction = ol.interaction.Draw.createBox()
break
}
drawInteraction = new ol.interaction.Draw({
source: vectorSource,
type,
geometryFunction,
style,
// freehand: true // 是否开启自由绘制模式
})
map.addInteraction(drawInteraction)
}
// 事件委托
const targetEle = document.querySelector(".draw-ul")
targetEle.addEventListener('click', evt => {
removeInteraction()
const targetEle = evt.target
const geomType = targetEle.dataset.type
if (geomType !== "None") {
toogleAciveClass(targetEle, ".draw-ul")
}
if (geomType) {
drawShape(geomType)
}
})
// 移除绘制控件
function removeInteraction() {
if (drawInteraction) {
map.removeInteraction(drawInteraction)
}
}
let lineWidth = 2.5
let lineDash = [30, 40, 50, 60]
layui.use(function () {
const slider = layui.slider;
// 线条宽度
slider.render({
elem: '#stroke-width-value',
value: 5, //初始值
change: function (value) {
lineWidth = value
const styleObj = {
width: lineWidth
}
setStyle(styleObj)
}
});
// 虚线间隔
slider.render({
elem: '#line-dash-value',
value: 0, //初始值
change: function (value) {
lineDash = [value, 40, 50, 60]
const styleObj = {
lineDash: lineDash
}
setStyle(styleObj)
}
});
// 偏移值
slider.render({
elem: '#line-dash-offset',
value: 0, //初始值
change: function (value) {
const styleObj = {
lineDashOffset: value
}
setStyle(styleObj)
}
});
});
layui.use(function () {
const form = layui.form;
const layer = layui.layer;
// radio 事件
form.on('radio(cap-radio-filter)', function (data) {
const elem = data.elem; // 获得 radio 原始 DOM 对象
const checked = elem.checked; // 获得 radio 选中状态
const value = elem.value; // 获得 radio 值
const styleObj = {
lineCap: value
}
setStyle(styleObj)
})
form.on('radio(join-radio-filter)', function (data) {
const elem = data.elem; // 获得 radio 原始 DOM 对象
const checked = elem.checked; // 获得 radio 选中状态
const value = elem.value; // 获得 radio 值
const styleObj = {
lineJoin: value
}
setStyle(styleObj)
})
});
function setStyle(styleObj) {
const { width, lineCap, lineJoin, lineDash, lineDashOffset } = styleObj
map.removeLayer(vectorLayer)
const style = new ol.style.Style({
fill: new ol.style.Fill({
color: "#9b65ff30"
}),
stroke: new ol.style.Stroke({
color: "yellow",
width: width || lineWidth,
lineCap: lineCap || 'round',
lineJoin: lineJoin || 'round',
lineDash: lineDash || lineDash,
lineDashOffset: lineDashOffset || 0
})
})
vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: style
})
map.addLayer(vectorLayer)
}
</script>
❝
OpenLayers示例数据下载,请在公众号后台回复:ol数据
全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试
❝
GIS之路公众号已经接入了智能助手,欢迎大家前来提问。
欢迎访问我的博客网站-长谈GIS:
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏+关注 哦!
本号不定时更新有关 GIS开发 相关内容,欢迎关注