arcgis.js中3d场景下,显示图片,并且文字位置在图片上方
在3D地图中显示自己的图片,并且在图片上显示文字。可以跟随点移动,追踪物体的信息显示。如果有什么问题,欢迎评论和指正
先看效果:
遇到的问题:
1.arcgis.js的3D地图中图片symbol和文字symbol的xoffset,yoffset是不管用的
2.每种字体的显示长度不同,显示长度与字符串字节数不同。
字符串长度是中文字或者中文符号2个字节长度,英语的都是1个字节长度。
字体显示长度与字符串字节长度不完全一样,有些字符可能是1.5个显示长度,这就需要你具体使用的字体去做改变了。
这个显示长度就像我们编辑word文档一样,在一行的最后位置写一个中文,光标就到下一行了,也可以写二个英语,光标也会到下一行。但有时还可以写三个英文字符(iii),光标才跳到下一行。这是我自己理解的字体显示长度。
3.文字永远是以点的中心对齐,我们要做到文字右对齐或者左对齐,我们就需要使用空格来使文字对齐,文字要在点的上面就在文字后面加\n(换行符),文字要在点的下方就在文字前面加\n,加多少个这就需要具体问题具体分析了。
计算文字显示长度方法和文字左对齐,在点的上。
//得到字体的显示长度,不是字节长度
//不同的字体(Microsoft YaHei、黑体、宋体),显示长度可能不同
function strlen(str) {
var len = 0;
var numChinese = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c != 105 && ((c >= 48 && c <= 57) || (c >= 97 && c <= 122))) { // 数字,小写字母,i是一个长度单位 47=/
len += 2
} else if (c != 73 && (c == 65306 || (c >= 65 && c <= 90) || c == 35282)) { //中文:冒号,"角"字c == 35282,大写英文字母,I是一个长度单位
len += 3
} else if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f) || c == 176) {
//单字节加1 ,176 = °符号,也是一个长度单位
// if (c != 47) {
len++;
// }
} else { //中文4个显示长度单位
len += 4;
numChinese++;
}
}
if (numChinese == 3) {
return len - numChinese + 3;
} else if (numChinese == 4) {
return len - numChinese + 3;
}
return len;
}
//根据自己的图片来调整换行的大小和空格的多少
function showDataFormatting(data) {
var dataStr = "";
//93字节 中文是2个字节 14行
var totalStrLength = 80;
var totalStrRow = 17;
for (let i = 0; i < data.length; i++) {
let current_data = data[i];
let currentLength = strlen(current_data);
let diffLength = totalStrLength - currentLength;
// let diffLength = totalStrLength - current_data.length;
while (diffLength) {
current_data += " ";
diffLength--;
}
console.log("current_data:" + current_data + "|");
dataStr += current_data + "\n";
}
let diffRow = totalStrRow - data.length;
while (diffRow) {
dataStr += "\n";
diffRow--;
}
return dataStr;
}
全部代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>3D 地图,图片和文字的显示</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<!-- 导入arcgis -->
<link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.22/"></script>
</head>
<body>
<div id="viewDiv"></div>
<script>
console.log("此文件可以介绍在3D地图中点的上面添加图片和文字");
//得到字体的显示长度,不是字节长度
//不同的字体(Microsoft YaHei、黑体、宋体),显示长度可能不同
function strlen(str) {
var len = 0;
var numChinese = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c != 105 && ((c >= 48 && c <= 57) || (c >= 97 && c <= 122))) { // 数字,小写字母,i是一个长度单位 47=/
len += 2
} else if (c != 73 && (c == 65306 || (c >= 65 && c <= 90) || c == 35282)) { //中文:冒号,"角"字c == 35282,大写英文字母,I是一个长度单位
len += 3
} else if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f) || c == 176) {
//单字节加1 ,176 = °符号,也是一个长度单位
// if (c != 47) {
len++;
// }
} else { //中文4个显示长度单位
len += 4;
numChinese++;
}
}
if (numChinese == 3) {
return len - numChinese + 3;
} else if (numChinese == 4) {
return len - numChinese + 3;
}
return len;
}
//根据自己的图片来调整换行的大小和空格的多少
function showDataFormatting(data) {
var dataStr = "";
//93字节 中文是2个字节 14行
var totalStrLength = 80;
var totalStrRow = 17;
for (let i = 0; i < data.length; i++) {
let current_data = data[i];
let currentLength = strlen(current_data);
let diffLength = totalStrLength - currentLength;
// let diffLength = totalStrLength - current_data.length;
while (diffLength) {
current_data += " ";
diffLength--;
}
console.log("current_data:" + current_data + "|");
dataStr += current_data + "\n";
}
let diffRow = totalStrRow - data.length;
while (diffRow) {
dataStr += "\n";
diffRow--;
}
return dataStr;
}
//使用arcgis.js
require([
"esri/Map",
"esri/views/SceneView",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/symbols/TextSymbol"
],
(Map, SceneView, MapView, FeatureLayer, Graphic, GraphicsLayer, TextSymbol) => {
let textsss = new TextSymbol();
console.log("textsss", textsss)
let centerPoint = [116, 39]; //大概是北京的经纬度
//底层
const map = new Map({
basemap: "osm" //查看地图的模式,官方还有其他的模式
});
//3D容器
const view = new SceneView({
container: "viewDiv", //与html元素绑定
map: map, //设置底层
zoom: 15, //初始地图距离大小
center: centerPoint //中心点(可以取小数) ,这里设置的北京
});
let graphicLayer = new GraphicsLayer({
maxScale: 5,
minScale: 1000000
});
map.add(graphicLayer);
// view.layer.add(graphicLayer);
//显示在图中的点
let point = {
type: "point",
longitude: centerPoint[0],
latitude: centerPoint[1],
hasZ: true, //开启Z轴
hasM: true, //以米为单位
z: 200 //
}
let pointSymbol = {
type: "simple-marker",
style: "circle",
color: [255, 0, 0], //[255,255,255] or "blue"
size: "12px",
outline: { //外边框
color: [255, 255, 255],
width: 1
}
}
let pointPopupTemplate = {
title: "title",
content: "hhhhh"
};
let pointGraphic = new Graphic({
geometry: point, //点的位置
symbol: pointSymbol, //点的图形
popupTemplate: pointPopupTemplate //弹窗
});
graphicLayer.add(pointGraphic);
//显示在图中的文字
let textPoint = {
type: "point",
x: centerPoint[0],
y: centerPoint[1],
hasZ: true, //开启Z轴
hasM: true, //以米为单位
z: 200 //
}
let textStr = showDataFormatting(["ID:" + 1,
"高度:" + 999 + "m",
"距离:" + 999 + "m",
"速度:" + 999 + "m/s",
"经/纬度:" + 999 + "°/" + 999 + "°",
"方位角:" + 99 + "°",
"水平仪测角:" + 99 + "°"
]);
//Microsoft YaHei:大小写英文 2,i I 1, 中文 3,° 1,数字2,m M N 3,. 1,/ 1,
//黑体:
//Microsoft YaHei:
//特殊 f<2 g>2 f+g=4
//1:i I
//2:a 0123456789 abc e
//3:D d A
//4:
let textSymbol = {
type: "text",
color: "black",
haloSize: "1px",
text: textStr,
// xoffset: 100,
// yoffset: 100,
font: {
size: 14,
family: "Microsoft YaHei", //Microsoft YaHei 黑体
// weight: "bold"
}
}
let textGraphic = new Graphic({
geometry: textPoint, //文字的位置
symbol: textSymbol //文字
});
let pictureSymbol2 = {
type: "point-3d",
symbolLayers: [{
type: "icon",
size: 200,
anchor: "bottom-right",
// xoffset: 100,
// yoffset: 100,
resource: {
href: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F03%2F11%2F29%2F5b494b3dd06fe_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1643867115&t=326b45732bb38c73c16b8febc2b56029"
},
material: {
color: [255, 255, 255, 1]
}
}]
};
let pictureGraphic = new Graphic({
geometry: textPoint, //图片的位置
symbol: pictureSymbol2 //图片
});
console.log("pictureSymbol2", pictureSymbol2)
console.log("textSymbol", textSymbol)
//添加到容器
graphicLayer.add(textGraphic);
graphicLayer.add(pictureGraphic);
console.log("view", view)
console.log("view.graphics.items", view.graphics.items)
})
</script>
</body>
</html>