div(或td)为50%透明(opacity:0.5),div(或td)里面的img添加opacity:1(不透明),但显示的结果img也是透明的

本文介绍了一种在CSS中创建透明边框同时保持内部元素不透明的方法,通过使用特定的滤镜和背景颜色属性实现,并确保了良好的浏览器兼容性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、原因分析:img继承了div的opacity属性,所以外面的DIV都透明了,那么它包含的所有元素都是透明的。
2、如果要实现透明边框,子元素不透明,那么就要用这个组合(原来的opacity属性要去掉):	       
        filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#3f000000',endColorstr='#3f000000');
        background-color:rgba(255,255, 255, 0.3)
     }
   但要注意这两个属性中的颜色,透明度一定要一致,这个兼容性最高,效果也最好。

    startColorStr:可选项。字符串(String)。设置或检索色彩渐变的开始颜色和透明度。 其格式为 #AARRGGBB 。 AA 、 RR 、 GG 、 BB 为十六进制正整数。取值范围为 00 - FF 。 RR 指定红色值, GG 指定绿色值, BB 指定蓝色值,参阅 #RRGGBB 颜色单位。 AA 指定透明度。 00 是完全透明。 FF 是完全不透明。超出取值范围的值将被恢复为默认值。 取值范围为 #FF000000 - #FFFFFFFF 。默认值为 #FF0000FF 。不透明蓝色。 EndColorStr:可选项。字符串(String)。设置或检索色彩渐变的结束颜色和透明度。参阅 startColorStr 属性。默认值为 #FF000000 。不透明黑色。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Materials Gallery</title> <style> /* 容器样式 */ .luxemg-container { max-width: 80%; margin: 0 auto; padding: 40px 20px; position: relative; } /* 标题区域 */ .luxemg-header { text-align: center; margin-bottom: 50px; padding-bottom: 20px; border-bottom: 1px solid #e0e0e0; } .luxemg-title { font-weight: 300; letter-spacing: 2px; color: #333; margin: 0 0 10px 0; font-size: 28px; } .luxemg-subtitle { color: #7a7a7a; max-width: 600px; margin: 0 auto; line-height: 1.6; } /* 网格布局 */ .luxemg-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 30px; } /* 卡片样式 */ .luxemg-card { background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 5px 15px rgba(0,0,0,0.05); transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; display: flex; flex-direction: column; height: 100%; } .luxemg-card:hover { transform: translateY(-8px); box-shadow: 0 12px 25px rgba(0,0,0,0.08); } .luxemg-card-image { height: 240px; overflow: hidden; background: #f8f8f8; } .luxemg-card-img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } .luxemg-card:hover .luxemg-card-img { transform: scale(1.05); } .luxemg-card-content { padding: 25px; flex-grow: 1; display: flex; flex-direction: column; } .luxemg-card-title { font-weight: 400; margin: 0 0 15px 0; font-size: 22px; letter-spacing: 1px; color: #222; } .luxemg-card-desc { color: #666; line-height: 1.7; margin: 0 0 20px 0; font-size: 16px; flex-grow: 1; } /* 详情按钮样式 */ .luxemg-detail-btn { display: inline-block; padding: 10px 20px; background: #000; color: white; border: 2px solid #000; border-radius: 4px; cursor: pointer; font-weight: 500; letter-spacing: 1px; text-transform: uppercase; font-size: 14px; transition: all 0.3s ease; align-self: flex-start; } .luxemg-detail-btn:hover { background: white !important; color: black !important; } /* 模态框样式 */ #luxemg-modal-container { position: fixed; top: 0; left: 10%; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: none; z-index: 10000; opacity: 0; transition: opacity 0.3s ease; } .luxemg-modal-wrapper { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; padding: 20px; box-sizing: border-box; } .luxemg-modal-content { background: white; width: 100%; max-width: 900px; max-height: 90vh; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 20px 40px rgba(0,0,0,0.3); transform: scale(0.95); transition: transform 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28), opacity 0.3s ease; opacity: 0; } .luxemg-modal-header { display: flex; justify-content: space-between; align-items: center; padding: 20px; border-bottom: 1px solid #eee; } .luxemg-modal-title { margin: 0; font-size: 24px; font-weight: 400; color: #333; } .luxemg-close-btn { background: none; border: none; font-size: 24px; cursor: pointer; color: #888; transition: color 0.3s; } .luxemg-close-btn:hover { color: #333; } .luxemg-modal-body { display: flex; overflow: auto; flex-grow: 1; padding: 0; } .luxemg-modal-image-container { width: 50%; min-width: 300px; background: #f8f8f8; display: flex; align-items: center; justify-content: center; padding: 30px; } .luxemg-modal-img { max-width: 100%; max-height: 400px; object-fit: contain; } .luxemg-modal-description { width: 50%; padding: 30px; overflow-y: auto; } .luxemg-modal-desc { line-height: 1.8; color: #555; } .luxemg-specs-table { width: 100%; border-collapse: collapse; margin-top: 25px; font-size: 15px; } .luxemg-specs-table th { padding: 10px; text-align: left; border-bottom: 1px solid #eee; background: #f5f5f5; } .luxemg-specs-table td { padding: 10px; border-bottom: 1px solid #eee; } /* 响应式设计 */ @media (max-width: 1024px) { .luxemg-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 768px) { .luxemg-container { padding: 30px 15px; } .luxemg-grid { grid-template-columns: 1fr; gap: 25px; } .luxemg-card { max-width: 500px; margin: 0 auto; } .luxemg-modal-body { flex-direction: column; } .luxemg-modal-image-container, .luxemg-modal-description { width: 100% !important; } .luxemg-modal-image-container { height: 300px; min-height: auto; } } @media (max-width: 480px) { .luxemg-title { font-size: 24px; } .luxemg-card-title { font-size: 20px; } .luxemg-card-desc { font-size: 15px; } } @media (max-height: 700px) { .luxemg-modal-content { max-height: 85vh; } } </style> </head> <body> <div class="luxemg-container"> <!-- 材料展示网格 --> <div class="luxemg-grid"> <!-- 材料项 1 --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://www.fetchingpack.com/wp-content/uploads/2025/06/ChatGPT-Image-2025年6月18日-16_45_42_compressed.png" alt="double-sided coated paper" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">double-sided coated paper</h3> <button class="luxemg-detail-btn" data-luxemg-modal="modal1">VIEW MORE</button> </div> </div> <!-- 材料项 2 --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/600x400/e8极8e8/999999?text=Oak+Hardwood" alt="Oak Hardwood" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Oak Hardwood</h3> <p class="luxemg-card-desc">European white oak with natural grain patterns...</p> <button class="luxemg-detail-btn" data-luxemg-modal="modal2">VIEW MORE</button> </div> </div> <!-- 材料项 3 --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/600x400/e8e8e8/999999?text=Brushed+Brass" alt="Brushed Brass" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Brushed Brass</h3> <p class="luxemg-card-desc">Hand-finished brass with subtle texture...</p> <button class="luxemg-detail-btn" data-luxemg-modal="modal3">VIEW MORE</button> </div> </div> <!-- 材料项 4 --> <div class="luxemg-card"> <div class="luxemg-card-image"> <img src="https://via.placeholder.com/600x400/e8e8e8/999999?text=Ceramic+Tiles" alt="Ceramic Tiles" class="luxemg-card-img"> </div> <div class="luxemg-card-content"> <h3 class="luxemg-card-title">Ceramic Tiles</h3> <p class="luxemg-card-desc">High-gloss ceramic tiles with exceptional durability...</p> <button class="luxemg-detail-btn" data-luxemg-modal="modal4">VIEW MORE</button> </div> </div> </div> </div> <!-- 模态框容器 --> <div id="luxemg-modal-container" class="luxemg-modal-container"> <div class="luxemg-modal-wrapper"> <div class="luxemg-modal-content"> <div class="luxemg-modal-header"> <h3 id="luxemg-modal-title" class="luxemg-modal-title">Material Details</h3> <button id="luxemg-close-modal" class="luxemg-close-btn">×</button> </div> <div class="luxemg-modal-body"> <div class="luxemg-modal-image-container"> <img id="luxemg-modal-image" class="luxemg-modal-img" src="" alt="Material"> </div> <div class="luxemg-modal-description"> <div id="luxemg-modal-description" class="luxemg-modal-desc"></div> <table class="luxemg-specs-table"> <thead> <tr> <th>Property</th> <th>Value</th> </tr> </thead> <tbody id="luxemg-modal-specs" class="luxemg-specs-body"></tbody> </table> </div> </div> </div> </div> </div> <script> // 使用IIFE创建私有作用域避免全局污染 (function() { // 材料详情数据 - 使用唯一前缀 const luxemgMaterialDetails = { modal1: { title: "Italian Marble", image: "https://via.placeholder.com/800x600/e8e8e8/999999?text=Italian+Marble+Detail", description: "<p>Premium Carrara marble quarried directly from the Apuan Alps in Tuscany, Italy. This exquisite natural stone features distinctive soft gray veining on a white or blue-gray background, creating timeless elegance.</p><p>Each slab is carefully selected for its unique pattern and quality, ensuring minimal imperfections. Ideal for high-end countertops, flooring, and feature walls. The marble undergoes a specialized polishing process to enhance its natural luster and durability.</p>", specs: [ { property: "Origin", value: "Carrara, Italy" }, { property: "Hardness", value: "3-4 on Mohs scale" }, { property: "Thickness", value: "2cm, 3cm" }, { property: "Finish", value: "Polished, Honed" }, { property: "Maintenance", value: "Sealing recommended" } ] }, modal2: { title: "Oak Hardwood", image: "https://via.placeholder.com/800x600/e8e8e8/999999?text=Oak+Hardwood+Detail", description: "<p>European white oak (Quercus robur) sourced from sustainably managed forests. This premium hardwood features a straight grain with occasional swirls and burls, offering a warm, natural appearance.</p><p>The wood undergoes a meticulous kiln-drying process to achieve optimal moisture content (8-10%), ensuring dimensional stability. Available in various grades from rustic to select, suitable for flooring, furniture, and architectural elements. The natural tannin content provides inherent resistance to insects and decay.</p>", specs: [ { property: "Species", value: "Quercus robur" }, { property: "Janka Hardness", value: "1360 lbf" }, { property: "Density", value: "720 kg/m³" }, { property: "Moisture Content", value: "8-10%" }, { property: "Sustainability", value: "FSC Certified" } ] }, modal3: { title: "Brushed Brass", image: "https://via.placeholder.com/800x600/e8e8e8/999999?text=Brushed+Brass+Detail", description: "<p>Hand-finished brass with a distinctive brushed texture that diffuses light and minimizes fingerprints. This premium alloy contains 85% copper and 15% zinc, offering a warm golden hue that develops a rich patina over time.</p><p>The brushing process creates subtle linear patterns that enhance depth and character. A protective lacquer coating is applied to preserve the finish while allowing for natural aging. Ideal for hardware, fixtures, and decorative accents in both contemporary and traditional settings.</p>", specs: [ { property: "Composition", value: "85% Copper, 15% Zinc" }, { property: "Finish", value: "Satin Brushed" }, { property: "Thickness", value: "1.2mm - 3mm" }, { property: "Protection", value: "Clear Lacquer Coated" }, { property: "Patina Development", value: "Slow, even" } ] }, modal4: { title: "Ceramic Tiles", image: "https://via.placeholder.com/800x600/e8e8e8/999999?text=Ceramic+Tiles+Detail", description: "<p>High-gloss ceramic tiles manufactured using advanced digital printing technology that replicates natural stone with remarkable fidelity. The durable glaze is formulated for exceptional scratch and stain resistance.</p><p>These tiles feature a through-body color composition, meaning any chips or scratches are less noticeable. The rectified edges allow for minimal grout lines (as small as 1.5mm), creating a seamless appearance. Suitable for both walls and floors in high-traffic areas.</p>", specs: [ { property: "Material", value: "Porcelain Ceramic" }, { property: "PEI Rating", value: "IV (Heavy Traffic)" }, { property: "Water Absorption", value: "<0.5%" }, { property: "Slip Resistance", value: "R10 (Dry)" }, { property: "Sizes", value: "60x60cm, 30x60cm" } ] } }; // DOM元素引用 const luxemgModalContainer = document.getElementById('luxemg-modal-container'); const luxemgModalTitle = document.getElementById('luxemg-modal-title'); const luxemgModalImage = document.getElementById('luxemg-modal-image'); const luxemgModalDescription = document.getElementById('luxemg-modal-description'); const luxemgModalSpecs = document.getElementById('luxemg-modal-specs'); const luxemgCloseModal = document.getElementById('luxemg-close-modal'); // 打开模态框函数 function openLuxemgModal(modalId) { const material = luxemgMaterialDetails[modalId]; const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); if (!material) { console.error("Material details not found for:", modalId); return; } // 填充模态框内容 luxemgModalTitle.textContent = material.title; luxemgModalImage.src = material.image; luxemgModalImage.alt = material.title; luxemgModalDescription.innerHTML = material.description; // 填充技术规格 luxemgModalSpecs.innerHTML = ''; material.specs.forEach(spec => { const row = document.createElement('tr'); row.innerHTML = ` <td>${spec.property}</td> <td>${spec.value}</td> `; luxemgModalSpecs.appendChild(row); }); // 显示模态框 luxemgModalContainer.style.display = 'block'; // 强制重绘确保动画执行 void luxemgModalContainer.offsetWidth; // 应用显示动画 setTimeout(() => { luxemgModalContainer.style.opacity = '1'; modalContent.style.transform = 'scale(1)'; modalContent.style.opacity = '1'; }, 10); // 禁止背景滚动 document.body.style.overflow = 'hidden'; } // 关闭模态框函数 function closeLuxemgModal() { const modalContent = luxemgModalContainer.querySelector('.luxemg-modal-content'); luxemgModalContainer.style.opacity = '0'; modalContent.style.transform = 'scale(0.95)'; modalContent.style.opacity = '0'; setTimeout(() => { luxemgModalContainer.style.display = 'none'; document.body.style.overflow = ''; }, 300); } // 事件绑定函数 function initLuxemgGallery() { // 绑定关闭按钮 luxemgCloseModal.addEventListener('click', closeLuxemgModal); // 点击背景关闭 luxemgModalContainer.addEventListener('click', function(e) { if (e.target === this) closeLuxemgModal(); }); // ESC键关闭 document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeLuxemgModal(); }); // 绑定详情按钮 const detailButtons = document.querySelectorAll('.luxemg-detail-btn'); detailButtons.forEach(button => { button.addEventListener('click', function() { const modalId = this.getAttribute('data-luxemg-modal'); console.log("Opening modal:", modalId); openLuxemgModal(modalId); }); }); console.log("Gallery initialized. Found", detailButtons.length, "detail buttons."); } // DOM加载完成后初始化 document.addEventListener('DOMContentLoaded', initLuxemgGallery); })(); </script> </body> </html> 去掉这段代码中的卡片上的文字描述,保留标题和按钮
06-20
An error occurred while rendering. Rendering has stopped. ReferenceError: shouldShow is not defined ReferenceError: shouldShow is not defined at http://localhost:8001/src/components/common-map/live-map.vue?t=1751774207331:38:23 at Proxy.forEach (<anonymous>) at http://localhost:8001/src/components/common-map/live-map.vue?t=1751774207331:37:28 at invokeFunc (http://localhost:8001/node_modules/.vite/deps/lodash.js?v=6636ce6c:3839:28) at leadingEdge (http://localhost:8001/node_modules/.vite/deps/lodash.js?v=6636ce6c:3845:30) at debounced (http://localhost:8001/node_modules/.vite/deps/lodash.js?v=6636ce6c:3887:24) at tD.raiseEvent (http://localhost:8001/libs/Cesium/Cesium.js:96:1282) at Jt._updateCameraChanged (http://localhost:8001/libs/Cesium/Cesium.js:11295:124016) at Xi.initializeFrame (http://localhost:8001/libs/Cesium/Cesium.js:12477:35438) at uC.render (http://localhost:8001/libs/Cesium/Cesium.js:12479:1576) 如图所示报错为什么 修改以下代码:<template> <div id="cesiumContainer"></div> <div ref="miniMapContainer" class="mini-map" @click="handleMiniMapClick"> <div class="location-indicator" :style="indicatorStyle"></div> <!-- 四个角折角 --> <div class="corner corner-top-left"></div> <div class="corner corner-top-right"></div> <div class="corner corner-bottom-left"></div> <div class="corner corner-bottom-right"></div> <!-- <div class="camera-icon">📷</div> --> <div class="focus-effect"></div> <div class="pulse"></div> </div> <Search @location-selected="handleLocationSelected" /> <LocationBar v-if="loaded" :update-interval="100" :use-dms-format="useDmsFormat" /> </template> <style> /* @import "/temp/css/divGraphic.css"; */ </style> <script setup lang="ts"> import { computed, onUnmounted, onMounted, reactive } from "vue"; import LocationBar from "./location-bar.vue"; import Search from "./search.vue"; import initMap from "./init"; import { ref } from "vue"; import { throttle } from 'lodash'; import { loadRipplePoints, createMultipleRippleCircles } from './circle.js'; import { $prototype } from "../../main.ts"; const miniMapContainer = ref<HTMLElement>(); let viewIndicator: Rectangle; // 视图指示器样式 const currentPosition = reactive({ longitude: 113.361538, latitude: 27.339318, }); // 株洲市范围常量 const ZHUZHOU_EXTENT = { west: 112.5, // 株洲市西边界 east: 114.5, // 株洲市东边界 south: 26.0, // 株洲市南边界 north: 28.0 // 株洲市北边界 }; const rippleEntities = ref<any[]>([]); // 存储波纹圆实体 const heightThreshold = 80000; // 高度阈值(),高于此值隐藏波纹圆 // 高度节流函数 const updateRippleVisibility = throttle(() => { if (!$prototype.$map || rippleEntities.value.length === 0) return; rippleEntities.value.forEach(entity => { entity.show = shouldShow; }); }, 200); // 每200毫秒最多执行一次 // 更新指示器位置 const updateIndicatorPosition = () => { if (!$prototype.$map) return; const camera = $prototype.$map.camera; const rect = camera.computeViewRectangle(); if (!rect) return; // 计算在株洲市范围内的相对位置 const center = Cesium.Rectangle.center(rect); const lon = Cesium.Math.toDegrees(center.longitude); const lat = Cesium.Math.toDegrees(center.latitude); const lonPercent = ((lon - ZHUZHOU_EXTENT.west) / (ZHUZHOU_EXTENT.east - ZHUZHOU_EXTENT.west)) * 100; const latPercent = 100 - ((lat - ZHUZHOU_EXTENT.south) / (ZHUZHOU_EXTENT.north - ZHUZHOU_EXTENT.south)) * 100; // 更新CSS指示器 indicatorStyle.value = { left: `${lonPercent}%`, top: `${latPercent}%`, display: "block" }; }; // 更新鹰眼地图 - 只更新指示器位置 const updateOverview = () => { if (!$prototype.$map || !overviewViewer.value) return; // 获取主地图的当前视图中心 const rectangle = $prototype.$map.camera.computeViewRectangle(); if (!rectangle) return; const center = Cesium.Rectangle.center(rectangle); currentPosition.longitude = Cesium.Math.toDegrees(center.longitude); currentPosition.latitude = Cesium.Math.toDegrees(center.latitude); // 更新指示器位置 updateIndicatorPosition(); }; const overviewViewer = ref(null); // 初始化鹰眼地图 - 使用株洲市影像 const initMiniMap = () => { Cesium.Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxMDhlNDdmYy03NzFhLTQ1ZTQtOWQ3NS1lZDAzNDc3YjE4NDYiLCJpZCI6MzAxNzQyLCJpYXQiOjE3NDcwNTMyMDN9.eaez8rQxVbPv2LKEU0sMDclPWyHKhh1tR27Vg-_rQSM"; if (!miniMapContainer.value) return; // 创建株洲市专用影像提供器 const zhuzhouProvider = new Cesium.UrlTemplateImageryProvider({ url: "http://124.232.190.30:9000/proxy/pk1725866655224/map/zzzsyx_18/{z}/{x}/{y}.png", minimumLevel: 1, maximumLevel: 17, crs: "EPSG:3857", }); // 鹰眼地图初始化 - 使用株洲市影像 overviewViewer.value = new Cesium.Viewer(miniMapContainer.value, { sceneMode: Cesium.SceneMode.SCENE2D, baseLayerPicker: false, homeButton: false, timeline: false, navigationHelpButton: false, animation: false, scene3DOnly: true, selectionIndicator: false, infoBox: false, imageryProvider: zhuzhouProvider, // 使用株洲市影像 terrainProvider: window.Cesium.createWorldTerrain(), }); // 设置固定视野为株洲市范围 overviewViewer.value.camera.setView({ destination: Cesium.Rectangle.fromDegrees( ZHUZHOU_EXTENT.west, ZHUZHOU_EXTENT.south, ZHUZHOU_EXTENT.east, ZHUZHOU_EXTENT.north ) }); // 隐藏控件 var toolbar = overviewViewer.value.container.getElementsByClassName("cesium-viewer-toolbar")[0]; if (toolbar) toolbar.style.display = "none"; overviewViewer.value.cesiumWidget.creditContainer.style.display = "none"; }; // 初始化视图指示器 function initRectangle() { // 创建视图指示器(株洲市范围框) viewIndicator = overviewViewer.value.entities.add({ rectangle: { coordinates: new Cesium.CallbackProperty(() => { return Cesium.Rectangle.fromDegrees( ZHUZHOU_EXTENT.west, ZHUZHOU_EXTENT.south, ZHUZHOU_EXTENT.east, ZHUZHOU_EXTENT.north ); }, false), material: Cesium.Color.RED.withAlpha(0.3), outline: true, outlineColor: Cesium.Color.RED, outlineWidth: 2, }, }); } // 指示器样式计算 const indicatorStyle = computed(() => { return {}; // 由updateIndicatorPosition直接设置 }); const loaded = ref(false); const useDmsFormat = ref(false); function addDemoGraphics() { const chinaBoundary = $prototype.$map.dataSources.add( Cesium.GeoJsonDataSource.load("/shp_zz.geojson", { stroke: Cesium.Color.WHITE, fill: false, clampToGround: true, describe: null, }) ); chinaBoundary.then((dataSource) => { const entities = dataSource.entities.values; for (let entity of entities) { if (entity.polyline) { entity.polyline.fill = false; } } }); } function flyToDes() { const center = Cesium.Cartesian3.fromDegrees(-98.0, 40.0); $prototype.$map.camera.flyTo({ destination: new Cesium.Cartesian3( -2432812.6687511606, 5559483.804371395, 2832009.419525571 ), orientation: { heading: 6.283185307179421, pitch: -1.0472145569408116, roll: 6.2831853071795205, }, complete: function () {}, }); } // 监听主地图相机变化 const setupCameraListener = () => { $prototype.$map.camera.changed.addEventListener(updateOverview); }; // 鹰眼地图点击处理 const handleMiniMapClick = (event: MouseEvent) => { if (!miniMapContainer.value || !overviewViewer.value) return; const rect = miniMapContainer.value.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; // 计算在固定范围内的相对位置 const xPercent = (x / rect.width) * 100; const yPercent = (y / rect.height) * 100; // 转换为株洲市范围内的经纬度 const lon = ZHUZHOU_EXTENT.west + (xPercent / 100) * (ZHUZHOU_EXTENT.east - ZHUZHOU_EXTENT.west); const lat = ZHUZHOU_EXTENT.north - (yPercent / 100) * (ZHUZHOU_EXTENT.north - ZHUZHOU_EXTENT.south); // 主地图飞向点击位置 $prototype.$map.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(lon, lat, 1000000), }); }; function addImage() { var rightImageProvider = new Cesium.UrlTemplateImageryProvider({ name: "影像图", type: "xyz", layer: "vec_d", url: "http://124.232.190.30:9000/proxy/pk1725866655224/map/zzzsyx_18/{z}/{x}/{y}.png", minimumLevel: 1, maximumLevel: 17, crs: "EPSG:3857", }); $prototype.$map.imageryLayers.addImageryProvider(rightImageProvider); rightImageProvider.splitDirection = Cesium.SplitDirection.right; } onMounted(() => { initMap(); addImage(); loaded.value = true; addDemoGraphics(); flyToDes(); initMiniMap(); setupCameraListener(); setTimeout(function () { initRectangle(); }, 2000); (async () => { try { const ripplePoints = await loadRipplePoints(); rippleEntities.value = createMultipleRippleCircles( $prototype.$map, ripplePoints ); $prototype.$map.camera.changed.addEventListener(updateRippleVisibility); updateRippleVisibility(); } catch (error) { console.error('加载波纹圆失败:', error); } })(); }); let currentMarker: any = null; const createMarker = (location: { lng: number; lat: number; name: string }) => { if (currentMarker) { $prototype.$map.entities.remove(currentMarker); } currentMarker = $prototype.$map.entities.add({ position: Cesium.Cartesian3.fromDegrees( location.lng, location.lat, 50 ), point: { pixelSize: 200, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2, heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, }, label: { text: location.name, font: "40px sans-serif", fillColor: Cesium.Color.WHITE, outlineColor: Cesium.Color.BLACK, outlineWidth: 1, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -20), heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000), }, description: `<div style="padding: 10px;"> <h3 style="margin: 0 0 5px 0;">${location.name}</h3> <p>经度:${location.lng.toFixed(6)}</p> <p>纬度:${location.lat.toFixed(6)}</p> </div>`, }); return currentMarker; }; const handleLocationSelected = (location: { lng: number; lat: number; name: string; }) => { if (!$prototype.$map) return; const destination = Cesium.Cartesian3.fromDegrees( location.lng, location.lat, 200 ); $prototype.$map.camera.flyTo({ destination, orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-45), roll: 0, }, duration: 2, complete: () => { createMarker(location); }, }); }; onUnmounted(() => { if ($prototype.$map) { $prototype.$map.destroy(); $prototype.$map = null; } if ($prototype.$map) { $prototype.$map.camera.changed.removeEventListener(updateRippleVisibility); } console.log("组件销毁"); }); const emit = defineEmits(["onload", "onclick"]); const initMars3d = async (option: any) => { emit("onclick", true); emit("onload", $prototype.$map); }; </script> <style lang="less"> /**cesium 工具按钮栏*/ .cesium-viewer-toolbar { top: auto !important; bottom: 35px !important; left: 12px !important; right: auto !important; } .cesium-toolbar-button img { height: 100%; } .cesium-viewer-toolbar > .cesium-toolbar-button, .cesium-navigationHelpButton-wrapper, .cesium-viewer-geocoderContainer { margin-bottom: 5px; float: left; clear: both; text-align: center; } .cesium-button { background-color: rgba(23, 49, 71, 0.8); color: #e6e6e6; fill: #e6e6e6; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); line-height: 32px; } .cesium-button:hover { background: #3ea6ff; } /**cesium 底图切换面板*/ .cesium-baseLayerPicker-dropDown { bottom: 0; left: 40px; max-height: 700px; margin-bottom: 5px; background-color: rgba(23, 49, 71, 0.8); } /**cesium 帮助面板*/ .cesium-navigation-help { top: auto; bottom: 0; left: 40px; transform-origin: left bottom; background: none; background-color: rgba(23, 49, 71, 0.8); .cesium-navigation-help-instructions { background: none; } .cesium-navigation-button { background: none; } .cesium-navigation-button-selected, .cesium-navigation-button-unselected:hover { background: rgba(0, 138, 255, 0.2); } } /**cesium 二维三维切换*/ .cesium-sceneModePicker-wrapper { width: auto; } .cesium-sceneModePicker-wrapper .cesium-sceneModePicker-dropDown-icon { float: right; margin: 0 3px; } /**cesium POI查询输入框*/ .cesium-viewer-geocoderContainer .search-results { left: 0; right: 40px; width: auto; z-index: 9999; } .cesium-geocoder-searchButton { background-color: rgba(23, 49, 71, 0.8); } .cesium-viewer-geocoderContainer .cesium-geocoder-input { background-color: rgba(63, 72, 84, 0.7); } .cesium-viewer-geocoderContainer .cesium-geocoder-input:focus { background-color: rgba(63, 72, 84, 0.9); } .cesium-viewer-geocoderContainer .search-results { background-color: rgba(23, 49, 71, 0.8); } /**cesium info信息框*/ .cesium-infoBox { top: 50px; background-color: rgba(23, 49, 71, 0.8); } .cesium-infoBox-title { background-color: rgba(23, 49, 71, 0.8); } /**cesium 任务栏的FPS信息*/ .cesium-performanceDisplay-defaultContainer { top: auto; bottom: 35px; right: 50px; } .cesium-performanceDisplay-ms, .cesium-performanceDisplay-fps { color: #fff; } /**cesium tileset调试信息面板*/ .cesium-viewer-cesiumInspectorContainer { top: 10px; left: 10px; right: auto; } .cesium-cesiumInspector { background-color: rgba(23, 49, 71, 0.8); } /**覆盖mars3d内部控件的颜色等样式*/ .mars3d-compass .mars3d-compass-outer { fill: rgba(23, 49, 71, 0.8); } .mars3d-contextmenu-ul, .mars3d-sub-menu { background-color: rgba(23, 49, 71, 0.8); > li > a:hover, > li > a:focus, > li > .active { background-color: #3ea6ff; } > .active > a, > .active > a:hover, > .active > a:focus { background-color: #3ea6ff; } } /* Popup样式*/ .mars3d-popup-color { color: #ffffff; } .mars3d-popup-background { background: rgba(23, 49, 71, 0.8); } .mars3d-popup-content { margin: 15px; } .mars3d-template-content label { padding-right: 6px; } .mars3d-template-titile { border-bottom: 1px solid #3ea6ff; } .mars3d-template-titile a { font-size: 16px; } .mars3d-tooltip { background: rgba(23, 49, 71, 0.8); border: 1px solid rgba(23, 49, 71, 0.8); } .mars3d-popup-btn-custom { padding: 3px 10px; border: 1px solid #209ffd; background: #209ffd1c; } .mars-dialog .mars-dialog__content { height: 100%; width: 100%; overflow: auto; padding: 5px; } .image { border: solid 2px #fff; } .content { height: 90%; padding-top: 10px; overflow-x: auto; overflow-y: auto; } .content-text { padding: 0 10px; text-indent: 30px; font-size: 17px; } .details-video { width: 100%; height: 760px; background-color: #000; } :where(.css-lt97qq9).ant-space { display: inline-flex; } :where(.css-lt97qq9).ant-space-align-center { align-items: center; } :where(.css-lt97qq9).ant-image .ant-image-mask { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; background: rgba(0, 0, 0, 0.5); cursor: pointer; opacity: 0; transition: opacity 0.3s; } :where(.css-lt97qq9).ant-image .ant-image-mask .ant-image-mask-info { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding: 0 4px; } :where(.css-1t97qq9)[class^="ant-image"] [class^="ant-image"], :where(.css-1t97qq9)[class*=" ant-image"] [class^="ant-image"], :where(.css-1t97qq9)[class^="ant-image"] [class*=" ant-image"], :where(.css-1t97qq9)[class*=" ant-image"] [class*=" ant-image"] { box-sizing: border-box; } :where(.css-lt97qq9).ant-image .ant-image-img { width: 100%; height: auto; vertical-align: middle; } </style> <style scoped> .mini-map-container { position: relative; width: 100%; height: 100%; } .main-viewer { width: 100%; height: 100%; } .mini-map { position: absolute; right: 3vw; bottom: 6vh; width: 12vw; height: 17vh; border: 2px solid #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 999; cursor: pointer; overflow: hidden; } .location-indicator { position: absolute; width: 14px; height: 14px; background: #ff3e3e; border: 2px solid white; border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 15px rgba(255, 62, 62, 1); z-index: 100; } .view-rectangle { position: absolute; border: 2px solid #00f2fe; z-index: 99; pointer-events: none; box-shadow: 0 0 20px rgba(0, 242, 254, 0.7); } /* 相机聚焦样式 - 四个角折角 */ .corner { position: absolute; width: 25px; height: 25px; z-index: 100; pointer-events: none; } .corner::before, .corner::after { content: ""; position: absolute; background: #00f2fe; box-shadow: 0 0 10px rgba(0, 242, 254, 0.8); } .corner-top-left { top: -2px; left: -2px; } .corner-top-left::before { top: 0; left: 0; width: 15px; height: 3px; } .corner-top-left::after { top: 0; left: 0; width: 3px; height: 15px; } .corner-top-right { top: -2px; right: -2px; } .corner-top-right::before { top: 0; right: 0; width: 15px; height: 3px; } .corner-top-right::after { top: 0; right: 0; width: 3px; height: 15px; } .corner-bottom-left { bottom: -2px; left: -2px; } .corner-bottom-left::before { bottom: 0; left: 0; width: 15px; height: 3px; } .corner-bottom-left::after { bottom: 0; left: 0; width: 3px; height: 15px; } .corner-bottom-right { bottom: -2px; right: -2px; } .corner-bottom-right::before { bottom: 0; right: 0; width: 15px; height: 3px; } .corner-bottom-right::after { bottom: 0; right: 0; width: 3px; height: 15px; } .camera-icon { position: absolute; top: 10px; right: 10px; color: #00f2fe; font-size: 24px; z-index: 100; text-shadow: 0 0 10px rgba(0, 242, 254, 0.8); } .focus-effect { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 98; border: 2px solid rgba(0, 242, 254, 0.2); border-radius: 5px; box-shadow: inset 0 0 30px rgba(0, 242, 254, 0.1); } .pulse { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 10px; height: 10px; border-radius: 50%; background: rgba(0, 242, 254, 0.7); box-shadow: 0 0 0 0 rgba(0, 242, 254, 0.7); animation: pulse 2s infinite; } ::v-deep.cesium-viewer-toolbar { display: none; } </style>
最新发布
07-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值