官方文档:http://ailabel.com.cn/public/ailabel/api/index.html#1
demo地址1: http://ailabel.com.cn/public/ailabel/demo/label/index.html
demo地址2: http://ailabel.com.cn/public/ailabel/demo/index.html
<template>
<div class="dashboard">
<div class="index_left">
<div class="index_div">
<div class="layer22">
<span class="info6">新建样本集</span>
</div>
</div>
<div class="index_div inputval">
<el-input
@input="changeinput"
class="index_input"
placeholder="输入数据名称或ID"
suffix-icon="el-icon-search"
v-model.trim="searchval"
>
</el-input>
</div>
<div class="index_list">
<div class="index_title">
<div>
<span>样本集</span>
<i>3</i>
</div>
<div>
<span>标注</span>
<!-- <i>1</i> -->
</div>
<div>
<span>样本量</span>
<!-- <i>5</i> -->
</div>
</div>
<template v-for="(item,index) in list">
<div @click="handClick(item,index)" :class="{ currcolor:index == currindex ? true : false}" class="index_item" :key="index">
<div>
<i></i>
<span>{
{
item.title}}</span>
</div>
<div>
<span>{
{
item.percentage}}</span>
</div>
<div>
<span>{
{
item.number}}</span>
</div>
</div>
</template>
</div>
</div>
<div class="index_right">
<div class="right_top_title">样本集:绝缘子缺陷</div>
<div class="index_detail" v-if="!flagswitch">
<div class="item_detail">
<p class="detail_p1">训练集</p>
<p class="detail_p2">Insulator / Images /</p>
<p class="detail_p3">50000 <span>张</span></p>
<span class="detail_line"></span>
<div class="item_detail_list">
<div v-for="(item,index) of 16" :key="index" class="item_detail_item">
<img src="@/assets/images/ai_img1.png" alt="">
</div>
</div>
<span class="detail_line"></span>
<div class="detail_complete">标注完成度</div>
<span class="detail_percentage">75%</span>
<div class="detail_btn" @click="gomark">
标注
</div>
</div>
<div class="item_detail">
<p class="detail_p1">训练集</p>
<p class="detail_p2">Insulator / Images /</p>
<p class="detail_p3">50000 <span>张</span></p>
<span class="detail_line"></span>
<div class="item_detail_list">
<div v-for="(item,index) of 16" :key="index" class="item_detail_item">
<img src="@/assets/images/ai_img1.png" alt="">
</div>
</div>
<span class="detail_line"></span>
<div class="detail_complete">标注完成度</div>
<span class="detail_percentage">75%</span>
<div class="detail_btn">
标注
</div>
</div>
<div class="item_detail">
<p class="detail_p1">训练集</p>
<p class="detail_p2">Insulator / Images /</p>
<p class="detail_p3">50000 <span>张</span></p>
<span class="detail_line"></span>
<div class="item_detail_list">
<div v-for="(item,index) of 16" :key="index" class="item_detail_item">
<img src="@/assets/images/ai_img1.png" alt="">
</div>
</div>
<span class="detail_line"></span>
<div class="detail_complete">标注完成度</div>
<span class="detail_percentage">75%</span>
<div class="detail_btn">
标注
</div>
</div>
</div>
<!-- 底部按钮 -->
<div class="detail_bottom_btn" v-if="!flagswitch">
<div class="btn1">添加样本</div>
<div class="btn2">重新配置</div>
<div class="btn3">删除此样本</div>
</div>
<!-- 材料查看 轮播标题 -->
<div class="index_lunbo_title" v-if="flagswitch">
<div class="title_first">
<span class="title_top">训练集</span>
<span class="title_btm">
<!-- Insulator / Images / Train -->
<!-- 导航 -->
<breadcrumb class="breadcrumb-container" />
</span>
</div>
<span class="title_line"></span>
<div class="title_pro">
标注进度:1,029 / 5,000
</div>
<div class="title_img">
<span>当前样本:</span>
<span class="active_img">img_2389.png</span>
</div>
<span class="title_line"></span>
<img class="title_rectangular" :class="[curMode == 1 ? 'curimgbor' : '']" @click="setMode('RECT')" src="@/assets/images/ai_rectangular.png" alt="">
<img class="title_polygon" :class="[curMode == 2 ? 'curimgbor' : '']" @click="setMode('POLYGON')" src="@/assets/images/ai_polygon.png" alt="">
<el-select class="input_select" size="mini" v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<!-- 轮播 标签-->
<div class="content_swiper" v-if="flagswitch">
<div class="big_img">
<!-- 容器层 -->
<div id="map"></div>
<!-- <img :src="curimg" alt=""> -->
<div class="big_bottom_btn">
<div class="btn_msg">
样本信息:<span>img_2389.png</span>
</div>
<div class="img_size">
<span>Width:1200px</span>
<span>Height:678px</span>
</div>
<div class="btn_label">
标签:<span>1</span>
</div>
<div class="btn_red" @click="clearbtn('flag')">
清除标注
</div>
<div class="btn_green" @click="savebtn">
完成
</div>
</div>
<button @click="zoomIn();">+放大</button>
<button @click="zoomOut();">-缩小</button>
<button @click="setMode('DRAWMASK');">涂抹</button>
<button @click="setMode('CLEARMASK');">擦除</button>
<button @click="setMode('MARKER');">注记</button>
<button @click="btnclearimg">清除图层</button>
<button @click="btnadd">添加图层</button>
<button @click="refresh">刷新图层</button>
<button @click="addmoredata">添加图形</button>
<div>
{
{
curtext}}
</div>
</div>
<div class="right_swiper">
<div class="swiper_top" @click="clickscroll(1)">
<img src="@/assets/images/ai_arrow_top.png" alt="">
</div>
<div class="swiper_list">
<div class="swiper-container">
<div class="swiper-wrapper">
<!-- transform: translate(-100%); translateY 竖向移动轮播 -->
<div
class="swiper-slide"
@click="handchange(item,index)"
:style="{transform:`${animate?`translateY(${type == 2? '-120%' : '+120%'})`:'none'}`,transition: `${animate?'all '+(duration/2000)+'s':'none'}`}"
v-for="(item,index) in imglist"
:key="index">
<img :src="item.url" alt="">
</div>
</div>
</div>
</div>
<div class="swiper_bottom" @click="clickscroll(2)">
<img src="@/assets/images/ai_arrow_btm.png" alt="">
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
mapGetters, mapState } from "vuex";
import getListMixin from '@/mixins/getlist'; // 列表元素
import {
debounce } from "@/utils/index"; // 引入防抖函数
import Breadcrumb from '@/components/Breadcrumb'; //路由导航
import AILabel from 'ailabel';
let that;
let drawingStyle; // 绘制样式
let gMap; // 标注容器
let Mode = ''; // 默认绘制类型
let gImageLayer; // 图片绘制
let gFirstFeatureLayer; // 实例化
let gFirstMaskLayer; // 涂抹层
let gFirstTextLayer; // 文本层
let targetMarker; // 更新视图
let targetText; // 更新标签
let gFirstMarker; // 标注
export default {
name: "Dashboard",
mixins:[getListMixin],
data() {
return {
searchval: "", // 搜索输入值
currindex:0, // 默认选中项
list: [{
title: '样本集1',
percentage: '80%',
number: 1518,
color: 1,
}, {
title: '样本集2',
percentage: '80%',
number: 1517,
color: 2,
}, {
title: '样本集3',
percentage: '80%',
number: 1516,
color: 3,
},{
title: '样本集4',
percentage: '80%',
number: 1515,
color: 3,
},{
title: '样本集5',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集6',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集7',
percentage: '60%',
number: 1513,
color: 3,
},{
title: '样本集8',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集9',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集10',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集11',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集12',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集13',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集14',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集15',
percentage: '60%',
number: 1515,
color: 3,
}], // 数据列表
options: [{
value: '黄金糕',
label: '黄金糕',
color: 'red'
}, {
value: '双皮奶',
label: '双皮奶',
color: 'white'
}, {
value: '蚵仔煎',
label: '蚵仔煎',
color: 'green'
}, {
value: '龙须面',
label: '龙须面',
color: 'pink'
}, {
value: '北京烤鸭',
label: '北京烤鸭',
color: 'blue'
}],
value: '黄金糕', // 当前选择框值
imglist:[
{
url: require('../../assets/images/ai_bj1.png'), name:"ai_bj1"
},
{
url: require('../../assets/images/ai_bj2.png'), name:"ai_bj2"
},
{
url: require('../../assets/images/ai_bj3.png'),name:"ai_bj3"
},
{
url: require('../../assets/images/ai_img1.png'),name:"ai_bj3"
},
{
url: require('../../assets/images/ai_bj1.png'), name:"ai_bj1"
},
{
url: require('../../assets/images/ai_bj2.png'), name:"ai_bj2"
},
{
url: require('../../assets/images/ai_bj3.png'),name:"ai_bj3"
},
], // 素材列表
curimg:'', // 当前大图 url或base64
timer: null, // 延时定时器
animate: false, // 轮播是否开启动画
duration: 1000, // 轮播动画延时
type:1, // 轮播方向
centerindex:2, // 轮播中间值
flagswitch:true, // 标注开关
rleData:[], // 最终图像标记
curMode:1, // 当前图形类型
curtext:'',
};
},
created() {
// this.timer = setInterval(this.scroll, this.duration);
this.curimg = this.imglist[this.centerindex].url;
that = this;
console.log(this.imglist.length);
console.log(this.rleData.length);
this.rleData.length = this.imglist.length;
console.log(this.rleData.length);
console.log(this.rleData);
this.rleData = this.addmoredatax;
console.log(this.addmoredatax);
console.log(this.name);
},
methods: {
setMode(mode) {
// console.log(mode);
gMap.setMode(mode);
// 后续对应模式处理
switch (gMap.mode) {
case 'PAN': {
break;
}
case 'MARKER': {
// 忽略
break;
}
case 'POINT': {
drawingStyle = {
fillStyle: '#9370DB'};
gMap.setDrawingStyle(drawingStyle);
break;
}
case 'CIRCLE': {
drawingStyle = {
fillStyle: '#9370DB', strokeStyle: '#0000FF', lineWidth: 2};
gMap.setDrawingStyle(drawingStyle);
break;
}
case 'LINE': {
drawingStyle = {
strokeStyle: '#FF00FF', lineJoin: 'round', lineCap: 'round', lineWidth: 10};
gMap.setDrawingStyle(drawingStyle);
break;
}
case 'POLYLINE': {
drawingStyle = {
strokeStyle: '#FF1493', lineJoin: 'round', lineCap: 'round', lineWidth: 10}
gMap.setDrawingStyle(drawingStyle);
break;
}
case 'RECT': {
drawingStyle = {
strokeStyle: '#0f0', lineWidth: 1}
gMap.setDrawingStyle(drawingStyle);
this.curMode = 1;
break;
}
case 'POLYGON': {
drawingStyle = {
strokeStyle: '#00f', fillStyle: '#0f0', globalAlpha: .3, lineWidth: 1, fill: true, stroke: true}
gMap.setDrawingStyle(drawingStyle);
this.curMode = 2;
break;
}
case 'DRAWMASK': {
drawingStyle = {
strokeStyle: 'rgba(255, 0, 0, .5)', fillStyle: '#00f', lineWidth: 20}
gMap.setDrawingStyle(drawingStyle);
break;
}
case 'CLEARMASK': {
drawingStyle = {
fillStyle: '#00f', lineWidth: 20}
gMap.setDrawingStyle(drawingStyle);
break;
}
default:
break;
}
},
// 去标注
gomark(item){
this.flagswitch = true;
},
// 监听输入框搜索
changeinput(){
if(!this.searchval){
this.$nextTick(()=>{
this.list = [{
title: '样本集1',
percentage: '80%',
number: 1518,
color: 1,
}, {
title: '样本集2',
percentage: '80%',
number: 1517,
color: 2,
}, {
title: '样本集3',
percentage: '80%',
number: 1516,
color: 3,
},{
title: '样本集4',
percentage: '80%',
number: 1515,
color: 3,
},{
title: '样本集5',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集6',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集7',
percentage: '60%',
number: 1513,
color: 3,
},{
title: '样本集8',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集9',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集10',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集11',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集12',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集13',
percentage: '60%',
number: 1514,
color: 3,
},{
title: '样本集14',
percentage: '60%',
number: 1519,
color: 3,
},{
title: '样本集15',
percentage: '60%',
number: 1515,
color: 3,
},{
title: '样本集16',
percentage: '90%',
number: 1519,
color: 3,
},{
title: '样本集17',
percentage: '90%',
number: 1515,
color: 3,
},{
title: '样本集18',
percentage: '90%',
number: 1519,
color: 3,
},{
title: '样本集19',
percentage: '90%',
number: 1515,
color: 3,
},{
title: '样本集20',
percentage: '90%',
number: 1519,
color: 3,
}] // 数据列表
})
}
let arr = this.list.filter((item,index)=>{
return item.percentage == this.searchval;
});
if(arr.length > 0){
this.list = arr;
}
},
// 手动触发轮播
handchange: debounce((item,index)=>{
// that.curimg = item.url;
// 大于2 和小于2的 方向处理
if(index > that.centerindex){
that.clickscroll(2);
}else if(index<that.centerindex){
that.clickscroll(1);
}
},300,false),
// 轮播滚动
clickscroll: debounce( type => {
// 方向赋值
that.type = type;
// type 1 向上 2 向下
that.animate = true; // 因为在消息向上滚动的时候需要添加css3过渡动画,所以这里需要设置true
// 清除标记
that.clearbtn();
that.timer = setTimeout(() => {
if(type == 2){
that.imglist.push(that.imglist.shift()); //删除数组的第一个元素并添加到数组的最后一项
that.rleData.push(that.rleData.shift()); //删除数组的第一个元素并添加到数组的最后一项
}else{
that.imglist.unshift(that.imglist.pop()); //删除数组的第一个元素并添加到数组的最后一项
that.rleData.unshift(that.rleData.pop()); //删除数组的第一个元素并添加到数组的最后一项
}
that.curimg = that.imglist[that.centerindex].url;
that.animate = false; //滑动完成后取消过渡动画,实现无缝滚动
// 重新渲染标记
that.clearbtn(); // 清除标记
that.btnclearimg(); // 清除图层
that.btnadd(); // 添加新图层
that.addmoredata(); // 添加图形
}, that.duration / 2);//滑动item项必须要在每次轮播开始前,所以时间必须比duration短
},300,false),
// 搜索列表点击事件
handClick(item,idx){
// 赋值当前项
this.currindex = idx;
// 展示样本集
this.flagswitch = false;
},
// 初始化画布 获取基本属性
onImageLoad(e){
console.log(e);
},
// 画完标记触发
onAnnoAdded(item){
},
// 清除标记
clearbtn(flag){
// 删除全部marker
gMap.markerLayer.removeAllMarkers();
// 删除全部text
gFirstTextLayer.removeAllTexts();
// 删除全部feature
gFirstFeatureLayer.removeAllFeatures();
// 删除全部涂抹
gFirstMaskLayer.removeAllActions();
},
// 刷新图层
refresh(){
gMap.refresh();
},
// 保存标记位置
savebtn(){
const rleData = gFirstFeatureLayer.getAllFeatures();
console.log('--rleData--', rleData);
this.rleData[this.currindex] = rleData;
this.$message({
message: '保存成功',
type: 'success'
})
},
// 标记组件初始化完成
onReady(){
},
// 读取默认数据
readydata(){
},
// 删除图层
btnclearimg(){
// gMap.removeAllLayers();
gMap.removeLayerById('first-layer-image');
},
// 添加图层
btnadd(){
gImageLayer = new AILabel.Layer.Image('first-layer-image', // id
{
src: this.curimg,
width: 790,
height: 520,
position: {
// 图片左上角坐标
x: 0,
y: 0
}
}, // imageInfo
{
name: '第一个图片图层'}, // props
{
zIndex: 5} // style
)
gMap.addLayer(gImageLayer);
},
// 缩小
zoomIn(){
gMap.zoomIn();
},
// 放大
zoomOut(){
gMap.zoomOut();
},
// 初始化容器
showmarkimg(){
// 创建容器
gMap = new AILabel.Map('map', {
center: {
x: 395, y: 260},
zoom: 800,
mode: 'RECT', // 绘制线段
refreshDelayWhenZooming: false, // 缩放时是否允许刷新延时,性能更优
zoomWhenDrawing: false,
panWhenDrawing: false
})
// 添加图片层
gImageLayer = new AILabel.Layer.Image('first-layer-image', // id
{
src: this.curimg,
width: 790,
height: 520,
position: {
// 图片左上角坐标
x: 0,
y: 0
}
}, // imageInfo
{
name: '第一个图片图层'}, // props
{
zIndex: 5} // style
)
gMap.addLayer(gImageLayer);
// 实例化
gFirstFeatureLayer = new AILabel.Layer.Feature(
'first-layer-feature', // id
{
name: '第一个矢量图层'}, // props
{
zIndex: 10} // style
);
gMap.addLayer(gFirstFeatureLayer);
// 涂抹层
gFirstMaskLayer = new AILabel.Layer.Mask(
'first-layer-mask', // id
{
name: '第一个涂抹图层'}, // props
{
zIndex: 11, opacity: .5} // style
);
gMap.addLayer(gFirstMaskLayer);
// 添加文本层
gFirstTextLayer = new AILabel.Layer.Text(
'first-layer-text', // id
{
name: '第一个文本图层'}, // props
{
zIndex: 12, opacity: 1} // style
);
gMap.addLayer(gFirstTextLayer);
// 添加图形
this.addmoredata();
},
// 添加图形
addmoredata(){
console.log(this.rleData);
let rectFeature; // 添加矩形
let gFirstFeaturePolygon; // 添加多边形
let gFirstText; // 添加文字
this.rleData && this.rleData[this.currindex] && this.rleData[this.currindex].forEach(ele => {
console.log(ele);
if(ele.type == "RECT"){
rectFeature = new AILabel.Feature.Rect(
ele.id, // id
ele.shape, // shape
ele.props, // props
ele.style // style
);
gFirstFeatureLayer.addFeature(rectFeature);
// 判断是否有 text
if(ele.props && ele.props.text){
gFirstText = new AILabel.Text(
ele.props.textId, // id
{
text: ele.props.text, position: {
x: ele.shape.x, y: ele.shape.y}, offset: {
x: 0, y: 0}}, // shape, 左上角
{
name: '第一个文本对象',textId: ele.props.textId, deleteMarkerId: ele.props.deleteMarkerId}, // props
{
fillStyle: '#F4A460', strokeStyle: '#D2691E', background: true, globalAlpha: 1, fontColor: '#0f0'} // style
);
gFirstTextLayer.addText(gFirstText);
}
}else if(ele.type == 'POLYGON'){
gFirstFeaturePolygon = new AILabel.Feature.Polygon(
ele.id, // id
ele.shape, // shape
ele.props, // props
ele.style // style
);
gFirstFeatureLayer.addFeature(gFirstFeaturePolygon);
if(ele.props && ele.props.text){
gFirstText = new AILabel.Text(
ele.props.textId, // id, // id
{
text: ele.props.text, position: ele.shape.points[0], offset: {
x: 0, y: 0}}, // shape, 左上角
{
name: '第一个文本对象',textId: ele.props.textId, deleteMarkerId: ele.props.deleteMarkerId }, // props
{
fillStyle: '#F4A460', strokeStyle: '#D2691E', background: true, globalAlpha: 1, fontColor: '#0f0'} // style
);
gFirstTextLayer.addText(gFirstText);
}
}
});
}
},
components: {
Breadcrumb,
},
computed: {
...mapGetters(["name","addmoredatax"]),
},
mounted() {
this.showmarkimg();
// 绘制结束
gMap.events.on('drawDone', (type, data, data1) => {
// console.log('type, data', type, data);
// 唯一ID
const relatedTextId = `label-text-id-${
+new Date()}`;
const relatedDeleteMarkerId = `label-marker-id-${
+new Date()}`;
console.log(type);
// 添加标注
if (type === 'MARKER') {
console.log("sssssss");
const marker = new AILabel.Marker(
relatedDeleteMarkerId, // id
{
src: require('../../assets/images/marker.png'),
position: data,
offset: {
x: -16,
y: 32
}
}, // markerInfo
{
name: '第一个marker注记'} // props
);
marker.events.on('click', marker => {
console.log('marker click');
gMap.markerLayer.removeMarkerById(marker.id);
});
gMap.markerLayer.addMarker(marker);
}
// 添加点
else if (type === 'POINT') {
const pointFeature = new AILabel.Feature.Point(
relatedDeleteMarkerId, // id
{
...data, sr: 3}, // shape
{
name: '第一个矢量图层',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId }, // props
drawingStyle // style
);
gFirstFeatureLayer.addFeature(pointFeature);
}
// 添加圆
else if (type === 'CIRCLE') {
// data 代表r半径shape;data1代表sr半径shape
const circleFeature = new AILabel.Feature.Circle(
relatedDeleteMarkerId, // id
data, // data1代表屏幕坐标 shape
{
name: '第一个矢量图层',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
{
fillStyle: '#F4A460', strokeStyle: '#D2691E', lineWidth: 2} // style
);
gFirstFeatureLayer.addFeature(circleFeature);
}
// 添加线段
else if (type === 'LINE') {
const scale = gMap.getScale();
const width = drawingStyle.lineWidth / scale;
const lineFeature = new AILabel.Feature.Line(
relatedDeleteMarkerId, // id
{
...data, width}, // shape
{
name: '第一个矢量图层',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
drawingStyle // style
);
gFirstFeatureLayer.addFeature(lineFeature);
}
// 添加多线段
else if (type === 'POLYLINE') {
const scale = gMap.getScale();
const width = drawingStyle.lineWidth / scale;
const polylineFeature = new AILabel.Feature.Polyline(
relatedDeleteMarkerId, // id
{
points: data, width}, // shape
{
name: '第一个矢量图层',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
drawingStyle // style
);
gFirstFeatureLayer.addFeature(polylineFeature);
}
// 添加矩形
else if (type === 'RECT') {
const rectFeature = new AILabel.Feature.Rect(
relatedDeleteMarkerId, // id
data, // shape
{
name: '矢量图形',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId, text: this.value}, // props
drawingStyle // style
);
gFirstFeatureLayer.addFeature(rectFeature);
// 添加feature标签名
const {
x: ltx, y: lty} = data;
const gFirstText = new AILabel.Text(
relatedTextId, // id
{
text: this.value, position: {
x: ltx, y: lty}, offset: {
x: 0, y: 0}}, // shape, 左上角
{
name: '第一个文本对象',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
{
fillStyle: '#F4A460', strokeStyle: '#D2691E', background: true, globalAlpha: 1, fontColor: '#0f0'} // style
);
gFirstTextLayer.addText(gFirstText);
}
// 添加多边形
else if (type === 'POLYGON') {
const polygonFeature = new AILabel.Feature.Polygon(
relatedDeleteMarkerId, // id
{
points: data}, // shape
{
name: '矢量图形2',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId, text: this.value }, // props
drawingStyle // style
);
gFirstFeatureLayer.addFeature(polygonFeature);
// 添加feature标签名
const {
x: ltx, y: lty} = data[0];
const gFirstText = new AILabel.Text(
relatedTextId, // id
{
text: this.value, position: {
x: ltx, y: lty}, offset: {
x: 0, y: 0}}, // shape, 左上角
{
name: '第一个文本对象',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
{
fillStyle: '#F4A460', strokeStyle: '#D2691E', background: true, globalAlpha: 1, fontColor: '#0f0'} // style
);
gFirstTextLayer.addText(gFirstText);
}
// 添加涂抹
else if (type === 'DRAWMASK') {
const scale = gMap.getScale();
const width = drawingStyle.lineWidth / scale;
const drawMaskAction = new AILabel.Mask.Draw(
relatedDeleteMarkerId, // id
'铅笔',
{
points: data, width}, // shape
{
name: '港币', price: '1元',textId: relatedTextId, deleteMarkerId: relatedDeleteMarkerId}, // props
drawingStyle // style
);
gFirstMaskLayer.addAction(drawMaskAction);
}
// 添加擦除
else if (type === 'CLEARMASK') {
const scale = gMap.getScale();
const width = drawingStyle.lineWidth / scale;
const clearMaskAction = new AILabel.Mask.Clear(
relatedDeleteMarkerId, // id
{
points: data, width} // shape
);
gFirstMaskLayer.addAction(clearMaskAction);
}
});
// click单击事件
gMap.events.on('click', point => {
// console.log('--click--', point);
});
gMap.events.on('boundsChanged', data => {
console.log('--map boundsChanged--',data);
});
gMap.events.on('featureSelected', feature => {
// 高亮选中feature
gMap.setActiveFeature(feature);
const markerId = feature.props.deleteMarkerId;
const textId = feature.props.textId;
// 禁止重复编辑
const mappedMarker = gMap.markerLayer.getMarkerById(markerId);
if (mappedMarker) {
return;
}
console.log("双击编辑");
let features;
if(feature.type == "POLYGON"){
// console.log(feature.shape.points);
features = feature.shape.points[1];
}else if (feature.type == "RECT"){
features = feature.getPoints()[1];
}
// 添加delete-icon
gFirstMarker = new AILabel.Marker(
markerId, // id
{
src: require('../../assets/images/delete.png'),
position: features, // 矩形右上角
offset: {
x: -20,
y: -4
}
}, // markerInfo
{
name: '第一个marker注记'} // props
);
gFirstMarker.events.on('click', marker => {
console.log(marker);
// 首先删除当前marker
gMap.markerLayer.removeMarkerById(marker.id);
// 删除对应text
gFirstTextLayer.removeTextById(textId);
// 删除对应feature
gFirstFeatureLayer.removeFeatureById(feature.id);
});
gMap.markerLayer.addMarker(gFirstMarker);
});
gMap.events.on('featureUnselected', feature => {
console.log('取消featureSelected');
gMap.setActiveFeature(null);
gMap.markerLayer.removeMarkerById(feature.props.deleteMarkerId);
});
gMap.events.on('featureUpdated', (feature, shape) => {
console.log("移动更新");
console.log("featureUpdated",feature,shape);
feature.updateShape(shape);
// 更新标记
// 更新text位置
// 唯一ID
const markerId = feature.props.deleteMarkerId;
const textId = feature.props.textId;
console.log(markerId,textId);
// 更新marker位置
targetMarker = gMap.markerLayer.getMarkerById(markerId);
// console.log(targetMarker);
targetMarker.updatePosition(feature.type == "POLYGON" ? feature.shape.points[1] : feature.getPoints()[1]);
// 更新text位置
targetText = gFirstTextLayer.getTextById(textId);
console.log('--targetText--', targetText);
targetText.updatePosition(feature.type == "POLYGON" ? feature.shape.points[0] : feature.getPoints()[0]);
});
gMap.events.on('featureDeleted', ({
id: featureId}) => {
gFirstFeatureLayer.removeFeatureById(featureId);
});
},
};
</script>
<style lang="scss">
@import "~@/styles/variables.scss";
.dashboard {
width: 100%;
height: 100%;
display: flex;
justify-content: flex-start;
.index_left {
width: 320px;
min-height: calc(100vh - 72px);
background-color: $backGrounds;
border-right: 2px solid $bordercolor;
// float: left;
display: flex;
flex-direction: column;
align-items: center;
.index_div {
border-bottom: 2px solid $bordercolor;
padding: 9px 0;
width: 100%;
.layer22 {
height: 36px;
border-radius: 18px;
padding: 10px 0;
background-color: rgba(0, 150, 136, 1);
width: 280px;
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
.info6 {
width: 55px;
display: block;
overflow-wrap: break-word;
color: rgba(252, 252, 252, 1);
font-size: 11px;
white-space: nowrap;
text-align: center;
}
}
}
.inputval {
padding: 0 5px;
i {
font-size: 18px;
}
}
.index_list{
width: 100%;
// height: 560px;
// overflow: scroll;
.index_title{
font-size: 13px;
color: $BIAOTIcolor;
width: 100%;
height: 42px;
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 2px solid $bordercolor;
&>div{
width: 100px;
margin-left: 30px;
display: flex;
justify-content: flex-start;
align-items: center;
}
i{
display: block;
width: 21px;
height: 18px;
background: #D7D7D7;
border-radius: 3px;
line-height: 18px;
text-align: center;
font-size: 9px;
color: #FFFFFF;
transform: scale(.9);
margin-left: 6px;
}
}
.index_item{
font-size: 12px;
color: $colors;
width: 100%;
height: 42px;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
border-bottom: 2px solid $bordercolor;
&>div{
width: 100px;
margin-left: 30px;
display: flex;
justify-content: flex-start;
align-items: center;
}
i{
display: block;
width: 16px;
height: 16px;
background: #da5f5f;
border-radius: 50%;
margin-right: 10px;
}
}
// 当前选中项
.currcolor{
color: #009688;
}
}
}
.index_right {
width: 100%;
min-height: calc(100vh - 72px);
display: flex;
flex-direction: column;
align-items: center;
background-color: $bottomback;
.right_top_title{
width: 900px;
// width: 100%;
height: 56px;
display: flex;
justify-content: center;
align-items: center;
font-size: 13px;
color: $colors;
background-color: $backGrounds;
border-bottom: 2px solid $bordercolor;
}
.index_detail{
width: 100%;
display: flex;
justify-content: center;
margin-top: 20px;
.item_detail{
width: 275px;
height: 557px;
margin: 0 10px;
background: $backGrounds;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
border-radius: 5px;
.detail_p1{
margin-top: 30px;
font-size: 11px;
color: $colors;
text-align: center;
}
.detail_p2{
margin-top: 15px;
font-size: 11px;
color: $XUNLIANcolor;
text-align: center;
}
.detail_p3{
margin-top: 15px;
font-size: 28px;
color: $colors;
font-weight: 600;
text-align: center;
span{
color: $BIAOTIcolor;
font-size: 9px;
}
}
.detail_line{
display: block;
width: 90% ;
padding: 0 5%;
height: 2px;
background: $bordercolor;
margin: 0 auto;
margin-top: 30px;
}
.item_detail_list{
width: 92%;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
margin: 0 auto;
margin-top: 30px;
border-radius: 24px;
border: 2px solid #D7D7D7;
padding: 2px;
.item_detail_item{
width: 59px;
height: 39px;
margin: 1px 0 0 2px;
box-sizing: border-box;
img{
width: 100%;
height: 100%;
}
}
.item_detail_item:nth-child(4) img{
border-top-right-radius: 24px;
}
.item_detail_item:nth-child(13) img{
border-bottom-left-radius: 24px;
}
.item_detail_item:first-child img{
border-top-left-radius: 24px;
}
.item_detail_item:last-child img{
border-bottom-right-radius: 24px;
}
}
.detail_complete{
width: 240px;
height: 44px;
font-size: 9px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: $XUNLIANcolor;
line-height: 44px;
text-align: center;
margin: 0 auto;
margin-top: 20px;
}
.detail_percentage{
display: block;
width: 100%;
height: 44px;
font-size: 21px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: $colors;
text-align: center;
line-height: 44px;
}
.detail_btn{
width: 110px;
height: 28px;
background: #009688;
border-radius: 20px;
border: 2px solid #D7D7D7;
margin: 0 auto;
font-size: 13px;
color: #FCFCFC;
display: flex;
justify-content: center;
align-items: center;
margin-top: 12px;
cursor: pointer;
}
}
}
// 底部btn
.detail_bottom_btn{
width: 100%;
max-width: 855px;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 50px;
div{
font-size: 13px;
color: #FCFCFC;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
height: 36px;
background: $bjcolor;
border-radius: 20px;
border: 2px solid #D7D7D7;
padding: 0 28px;
margin-left: 18px;
}
.btn3{
background-color: #F74236;
}
}
// 材料轮播标题
.index_lunbo_title{
width: 845px;
height: 72px;
background: $backGrounds;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
border-radius: 5px;
display: flex;
justify-content: flex-start;
align-items: center;
margin-top: 20px;
.title_first{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-left: 20px;
.title_top{
font-size: 11px;
color: $colors;
}
.title_btm{
font-size: 9px;
color: $activecolor;
margin-top: 10px;
min-width: 110px;
text-align: center;
.breadcrumb-container{
font-size: 9px;
line-height: 0;
span{
color: $activecolor !important;
}
}
}
}
.title_line{
width: 3px;
height: 32px;
background: $bordercolor;
margin: 0 25px;
}
.title_pro{
width: 144px;
// height: 44px;
font-size: 11px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #666666;
line-height: 16px;
}
.title_img{
width: 144px;
font-size: 11px;
.active_img{
color: $activecolor;
}
}
.title_rectangular{
width: 32px;
height: 32px;
cursor: pointer;
}
.title_polygon{
width: 30px;
height: 34px;
margin-left: 25px;
margin-right: 26px;
cursor: pointer;
}
.curimgbor{
background-color: #f0f0f0;
}
}
// 轮播
.content_swiper{
display: flex;
justify-content: flex-start;
width: 845px;
height: 436px;
margin-top: 29px;
.big_img{
width: 656px;
height: 436px;
#map{
width: 656px;
height: 436px;
border: 1px solid red;
position: relative;
cursor: pointer;
}
.ai-observer{
width: 650px !important;
height: 430px !important;
border: 1px solid #009688;// 轮播大图边框
background-color: #FFFFFF;
.vmr-g-image{
width: 650px !important;
height: 430px !important;
}
}
// img{
// display: block;
// width: 99% !important;
// height: 97.5% !important;
// top: 0;
// left: 0;
// right: 0;
// bottom: 0;
// margin: auto;
// }
.big_bottom_btn{
margin-top: 10px;
width: 656px;
padding: 0 20px;
height: 72px;
background: #FFFFFF;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
border-radius: 5px;
display: flex;
justify-content: flex-start;
align-items: center;
.btn_msg{
display: block;
height: 16px;
font-size: 11px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #666666;
span{
color: $activecolor;
}
}
.img_size{
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
span{
font-size: 11px;
color: $colors;
font-weight: 600;
margin: 3px 0;
margin-left: 50px;
}
}
.btn_label{
height: 16px;
font-size: 11px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: $colors;
line-height: 16px;
margin-left: 50px;
span{
color: $activecolor;
}
}
.btn_red{
width: 100px;
height: 36px;
background: #F74236;
border-radius: 20px;
border: 2px solid #D7D7D7;
font-size: 13px;
display: flex;
justify-content: center;
align-items: center;
margin-left: 55px;
color: $btncolor;
cursor: pointer;
}
.btn_green{
width: 100px;
height: 36px;
background: $bjcolor;
border-radius: 20px;
border: 2px solid #D7D7D7;
font-size: 13px;
display: flex;
justify-content: center;
align-items: center;
color: $btncolor;
margin-left: 16px;
cursor: pointer;
}
}
}
.right_swiper{
width: 160px;
height: 436px;
margin-left: 25px;
.swiper_top{
display: flex;
justify-content: center;
align-items: center;
width: 160px;
height: 28px;
background: #D7D7D7;
border-radius: 6px;
margin-bottom: 8px;
cursor: pointer;
img{
width: 12px;
height: 12px;
}
}
.swiper_bottom{
display: flex;
justify-content: center;
align-items: center;
width: 160px;
height: 28px;
background: #D7D7D7;
border-radius: 6px;
margin-top: 8px;
cursor: pointer;
img{
width: 12px;
height: 12px;
cursor: pointer;
}
}
.swiper_list{
display:flex;
flex-direction: column;
align-items: center;
}
}
}
.option_img{
width: 300px;
height: 400px;
}
}
}
.index_div {
.el-input input::-webkit-input-placeholder {
font-size: 11px;
color: #aaaaaa;
}
.el-input input::-moz-input-placeholder {
font-size: 11px;
color: #aaaaaa;
}
.el-input input::-ms-input-placeholder {
font-size: 11px;
color: #aaaaaa;
}
}
.index_div .el-input__inner {
border: none;
list-style: none;
background-color: $subMenuBg;
}
.index_lunbo_title .el-input__inner{
width: 200px;
height: 40px;
border-radius: 25px;
background-color: $bjcolor;
font-size: 13px;
color: #FCFCFC;
}
.el-select-dropdown__item{
// width: 240px;
height: 40px;
border-bottom: 2px solid $bordercolor;
span{
width: 100%;
display: block;
text-align: center;
}
}
.el-select-dropdown__item:last-child{
// width: 240px;
height: 40px;
border: none;
}
.el-select-dropdown__item.selected{
color: $activecolor;
span{
width: 100%;
display: block;
text-align: center;
}
}
.el-select__caret{
color: #FFFFFF !important;
}
.el-input__suffix{
right: 12px;
}
.el-input__inner{
padding-left: 25px !important;
}
.swiper-container {
position: relative;
width: 100%;
height: 365px;
overflow: hidden;
}
.swiper-wrapper {
position: absolute;
width: 100%;
top: -120px;
// height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.swiper-slide {
width: 154px;
height: 102px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid;
margin: 9px 0;
border-radius: 24px;
border: 2px solid #D7D7D7;
transition: all 1s ease;
img{
transition: all 1s ease;
width: 100%;
height: 100%;
border-radius: 24px;
cursor: pointer;
}
}
.swiper-wrapper .swiper-slide:nth-child(3){
transition: all 1s ease;
width: 160px;
height: 108px;
img{
transition: all 1s ease;
width: 100%;
height: 100%;
border-radius: 24px;
}
}
// 修改标签大小
.g-image-op-content{
height: 20px;
line-height: 20px;
padding: 0 5px;
font-size: 10px;
}
</style>
<div id="text"> </div><script> var oText=document.getElementById("text"); var num=0,timer=null; timer=setInterval(function(){ if(num==1...
记录一次心脏滴血靶场实验过程此文主要从几个方面记录本次心脏滴血的实验过程:心脏滴血的攻击原理和效果心脏滴血攻击过程复现实验结果和现象分析实验过程中遇到的问题以及解决方案https://blog.csdn.net/caozhk/article/details/23738971https://blog.csdn.net/yaofeiNO1/article/detail...
Verify that Docker Engine is installed correctly命令中抛出docker: Error response from daemon: could not select device driver的原因及解决办法
安装包只有 4.86MB:我的 CPU 型号:执行之后,只有一个竖条状面板,信息很简洁:我最关心的就是 CPU 温度:也提供了简单的配置面板,主要是更改软件显示数据的刷新频率的:更多Jerry的原创文章,尽在:“汪子熙”:...
一:GCC版本查看:版本查看: gcc --version g++ --version位置查看: which gcc which g++二:GCC多版本管理与切换:参考这篇博客:https://blog.csdn.net/menghuanbeike/article/details/79008640三:gcc4.8.5安装教程:参考这篇博客:https://ww...
win10系统使用久了,好多网友反馈说关于对win10系统设置局域网共享无需输入用户名和密码设置的方法,在使用win10系统的过程中经常不知道如何去对win10系统设置局域网共享无需输入用户名和密码进行设置,有什么好的办法去设置win10系统设置局域网共享无需输入用户名和密码呢?在这里小编教你只需要1.使用鼠标右键点击桌面,选择个性化,点击更改桌面图标,点击更改图标即可修改桌面图标。 2. 使用鼠...
http://www.sketchupbar.com/
一.作业内容 使用MATLAB形态学图像处理函数(选择其中3种或以上):bwmorph, bwareaopen, bwhitmiss,strel, imdilate, imerode, imopen, imclose, imtophat。二.作业分析clear;clc;% 首先读取图片 图片的命名方式按照功能i = imread('pic.jpg');Sou
aop是一个规范,是动态化的一个规范,一个标准aspectJ:一个开源的专门做aop的框架,spring框架集成了aspectJ框架,通过spring就能够使用aspectj的功能,实现方式有两种:1、使用xml的配置文件:配置全局事务2、使用注解,项目中.
苹果在AR一直布局VR,最近的苹果开发者大会上,果家终于放出大招:iOS移动端ARKit平台以及VR兼容新桌面操作系统macOS High Sierra和几个做算法设计的程序猿聊天,大家都觉得AR不是什么新东西,尤其是Pokemon Go推出的前后,好多大小公司都对AR有所涉猎,比如阿里的AR红包,百度的AR地图;墙外的科技公司也是百家齐放。这次苹果放出的ARKit相比之下到底有什么新意呢
背景一直听说IntelliJ IDEA很厉害,但工作中一直用的是Eclipse。这两天放假,准备来试用一下Idea。新建Eclipse项目这个步骤是为后面的工作,做好素材准备。这一步比较简单,过程:略。。。NOTE:截图的时候,还没有web.xml文件。需要在WEB-INF目录新建web.xml文件。Idea导入项目1. IDEA导入项目IDEA之前如果没有的打开过的话,刚需要先临时建一个工作空间...
Spring IOC介绍spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入和控制反转是一样的概念吗?接触新的知识,今天主要来简单的介绍一下在spring IOC中依赖注入的方法。依赖注入和控制反转,目的是为了使类与类之间解耦合...