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

天地图应用篇: 增加缩放、比例尺控件

天地图应用篇: 增加缩放、比例尺控件


案例截图:

  • 效果图示下:
    在这里插入图片描述

案例代码:

  • 代码示下:

    <template><div class="tianditu-map-container"><!-- 顶部搜索和天气栏 --><div class="map-top-bar"><div class="search-weather-box search-box-official"><el-autocompletev-if="mapOptions.showSearch"v-model="searchKeyword":fetch-suggestions="fetchSearchSuggestions"placeholder="搜索地名、公交站、地铁站"class="search-input"@select="handleSelectSuggestion"clearable><template #default="{ item, query, highlighted }"><div class="search-suggestion-item" :class="{ 'is-active': highlighted }"><span class="search-suggestion-icon">{{ getPoiIcon(item.catalog) }}</span><span class="search-suggestion-title" v-html="highlightKeyword(item.value, query)"></span><span class="search-suggestion-type">{{ item.catalog }}</span><span class="search-suggestion-meta">{{ item.address }}</span></div></template><template #append><el-button :icon="Search" @click="searchLocation" :loading="searchLoading"><!-- 搜索 --></el-button></template></el-autocomplete></div></div><!-- 右上角按钮组 --><div class="map-toolbar-top-right"><el-tooltip content="全屏" placement="left"><el-button v-if="mapOptions.showFullscreen" :icon="isFullscreen ? Fold : FullScreen" @click="toggleFullscreen" circle /></el-tooltip></div><!-- 地图容器 --><div id="tianditu-map" class="map-container"></div><!-- 标记管理和表单 --><div class="marker-form" v-if="showMarkerForm"><el-form :model="markerForm" label-width="100px"><el-form-item label="名称" prop="name"><el-input v-model="markerForm.name" placeholder="请输入标记名称" /></el-form-item><el-form-item label="纬度" prop="lat"><el-input v-model="markerForm.lat" type="number" placeholder="请输入纬度" /></el-form-item><el-form-item label="经度" prop="lng"><el-input v-model="markerForm.lng" type="number" placeholder="请输入经度" /></el-form-item><el-form-item label="描述" prop="description"><el-input v-model="markerForm.description" type="textarea" :rows="2" placeholder="请输入描述" /></el-form-item><el-form-item><el-button type="primary" @click="saveMarker">保存</el-button><el-button @click="cancelMarker">取消</el-button></el-form-item></el-form></div><div class="markers-list" v-if="markers.length > 0"><h4>已保存的标记</h4><el-table :data="markers" style="width: 100%"><el-table-column prop="name" label="名称" /><el-table-column prop="description" label="描述" /><el-table-column label="坐标" width="200"><template #default="scope">{{ scope.row.lat.toFixed(6) }}, {{ scope.row.lng.toFixed(6) }}</template></el-table-column><el-table-column label="操作" width="250"><template #default="scope"><el-button size="small" @click="centerOnMarker(scope.row)" :icon="Location">定位</el-button><el-button size="small" type="primary" @click="navigateToMarker(scope.row)" :icon="Position">导航</el-button><el-button size="small" type="danger" @click="removeMarker(scope.$index)" :icon="Delete">删除</el-button></template></el-table-column></el-table></div></div>
    </template><script setup>
    import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
    import { ElMessage, ElMessageBox } from 'element-plus'
    import { Location, Position, Search, FullScreen, Fold, Promotion, Guide, Place, School, Delete } from '@element-plus/icons-vue'
    import { h } from 'vue'// 天地图API密钥
    const TIANDITU_KEY = '08pfngl6ytjjs8sjgjeef7ac2lsiissc'// 响应式数据
    const markers = ref([])
    const showMarkerForm = ref(false)
    const markerForm = ref({name: '',lat: '',lng: '',description: ''
    })// 地图相关变量
    let markerObjs = []
    let mapObj = null
    let mapTypeControl = null
    let customScaleControl = null// 功能开关参数
    const mapOptions = reactive({showZoom: true, // 是否显示缩放控件showSearch: true, // 是否显示搜索框showLayerSwitch: true, // 是否显示图层切换控件showFullscreen: true, // 是否显示全屏切换控件// 比例尺配置控件showScale: true, // 是否显示比例尺控件scaleUnit: 'Km', // 默认值km,比例尺单位配置:'Km'(公里), 'mi'(英里), 'both'(双单位)scaleUnitDisplay: 'chinese' // 单位显示方式:'word'(英文单词), 'chinese'(汉字), 'both'(双语言)
    })// 其他状态
    const isFullscreen = ref(false)
    const searchKeyword = ref('')
    const searchLoading = ref(false)// 创建自定义比例尺
    function createCustomScale() {if (!mapObj) returnconst scaleContainer = document.createElement('div')scaleContainer.className = 'custom-scale-control'scaleContainer.style.cssText = `position: absolute;bottom: 10px;left: 10px;background: rgba(255, 255, 255, 0.9);border: 1px solid #ccc;border-radius: 2px;padding: 2px 4px;font-size: 11px;font-family: Arial, sans-serif;z-index: 1000;min-width: 60px;text-align: center;color: #333;`// 单位显示映射函数function getUnitDisplay(unit, value) {const unitMappings = {'Km': {'word': 'Km','chinese': '公里','both': 'Km/公里'},'m': {'word': 'm','chinese': '米','both': 'm/米'},'mi': {'word': 'mi','chinese': '英里','both': 'mi/英里'},'ft': {'word': 'ft','chinese': '英尺','both': 'ft/英尺'}}const displayMode = mapOptions.scaleUnitDisplayconst unitMap = unitMappings[unit] || { 'word': unit, 'chinese': unit, 'both': unit }return unitMap[displayMode] || unit}function updateScale() {const zoom = mapObj.getZoom()const center = mapObj.getCenter()const lat = center.getLat()// 计算比例尺const earthCircumference = 40075016.686const pixelsPerTile = 256const tilesPerZoom = Math.pow(2, zoom)const pixelsPerDegree = (pixelsPerTile * tilesPerZoom) / 360const metersPerDegree = earthCircumference * Math.cos(lat * Math.PI / 180) / 360const metersPerPixel = metersPerDegree / pixelsPerDegree// 计算合适的比例尺距离和宽度let targetDistance, scaleWidth, unit, displayTextif (mapOptions.scaleUnit === 'Km' || mapOptions.scaleUnit === 'both') {// 公里模式const mPerPixel = metersPerPixelconst targetWidth = 100 // 目标宽度(像素)let meters = mPerPixel * targetWidth// 选择合适的比例尺距离if (meters >= 1000) {// 超过1km,使用原来的逻辑const Km = meters / 1000if (Km >= 1000) {targetDistance = Math.floor(Km / 1000) * 1000unit = 'Km'} else if (Km >= 100) {targetDistance = Math.floor(Km / 100) * 100unit = 'Km'} else if (Km >= 10) {targetDistance = Math.floor(Km / 10) * 10unit = 'Km'} else if (Km >= 1) {targetDistance = Math.floor(Km)unit = 'Km'} else {targetDistance = Math.floor(Km * 1000)unit = 'm'}scaleWidth = targetDistance / (unit === 'Km' ? mPerPixel / 1000 : mPerPixel)} else {// 1km范围内,使用新的逻辑(500m, 300m, 200m, 100m, 50m, 30m, 20m, 10m, 1m)if (meters >= 500) {targetDistance = 500unit = 'm'} else if (meters >= 300) {targetDistance = 300unit = 'm'} else if (meters >= 200) {targetDistance = 200unit = 'm'} else if (meters >= 100) {targetDistance = 100unit = 'm'} else if (meters >= 50) {targetDistance = 50unit = 'm'} else if (meters >= 30) {targetDistance = 30unit = 'm'} else if (meters >= 20) {targetDistance = 20unit = 'm'} else if (meters >= 10) {targetDistance = 10unit = 'm'} else {targetDistance = 1unit = 'm'}scaleWidth = targetDistance / mPerPixel}const unitDisplay = getUnitDisplay(unit, targetDistance)displayText = `${targetDistance} ${unitDisplay}`} else if (mapOptions.scaleUnit === 'mi') {// 英里模式const mPerPixel = metersPerPixelconst targetWidth = 100let meters = mPerPixel * targetWidth// 选择合适的比例尺距离if (meters >= 1000) {// 超过1km,使用原来的逻辑const miPerPixel = mPerPixel * 0.000621371const Km = meters / 1000let mi = Km * 0.621371if (mi >= 100) {targetDistance = Math.floor(mi / 100) * 100unit = 'mi'} else if (mi >= 10) {targetDistance = Math.floor(mi / 10) * 10unit = 'mi'} else if (mi >= 1) {targetDistance = Math.floor(mi)unit = 'mi'} else {targetDistance = Math.floor(mi * 5280)unit = 'ft'}scaleWidth = targetDistance / (unit === 'ft' ? miPerPixel * 5280 : miPerPixel)} else {// 1km范围内,使用新的逻辑let targetMetersif (meters >= 500) {targetMeters = 500} else if (meters >= 300) {targetMeters = 300} else if (meters >= 200) {targetMeters = 200} else if (meters >= 100) {targetMeters = 100} else if (meters >= 50) {targetMeters = 50} else if (meters >= 30) {targetMeters = 30} else if (meters >= 20) {targetMeters = 20} else if (meters >= 10) {targetMeters = 10} else {targetMeters = 1}// 转换为英里const miles = targetMeters * 0.000621371if (miles >= 1) {targetDistance = Math.floor(miles)unit = 'mi'} else {targetDistance = Math.floor(miles * 5280)unit = 'ft'}scaleWidth = targetMeters / mPerPixel}const unitDisplay = getUnitDisplay(unit, targetDistance)displayText = `${targetDistance} ${unitDisplay}`}if (mapOptions.scaleUnit === 'both') {let miTextif (unit === 'Km') {const miles = targetDistance * 0.621371if (miles >= 1) {const miUnitDisplay = getUnitDisplay('mi', Math.floor(miles))miText = `${Math.floor(miles)} ${miUnitDisplay}`} else {const ftUnitDisplay = getUnitDisplay('ft', Math.floor(miles * 5280))miText = `${Math.floor(miles * 5280)} ${ftUnitDisplay}`}} else if (unit === 'm') {const miles = targetDistance * 0.000621371if (miles >= 1) {const miUnitDisplay = getUnitDisplay('mi', Math.floor(miles))miText = `${Math.floor(miles)} ${miUnitDisplay}`} else {const ftUnitDisplay = getUnitDisplay('ft', Math.floor(miles * 5280))miText = `${Math.floor(miles * 5280)} ${ftUnitDisplay}`}} else if (unit === 'mi') {const meters = targetDistance * 1609.34const mUnitDisplay = getUnitDisplay('m', Math.floor(meters))miText = `${Math.floor(meters)} ${mUnitDisplay}`} else {const meters = targetDistance * 5280 * 0.3048const mUnitDisplay = getUnitDisplay('m', Math.floor(meters))miText = `${Math.floor(meters)} ${mUnitDisplay}`}displayText = `${displayText} / ${miText}`}// 限制比例尺宽度在合理范围内,确保线条长度适中scaleWidth = Math.max(40, Math.min(120, scaleWidth))scaleContainer.innerHTML = `<div style="margin-bottom: 2px;">${displayText}</div><div style="height: 2px; background: #333; width: ${scaleWidth}px; margin: 0 auto;"></div>`}updateScale()mapObj.addEventListener('zoomend', updateScale)mapObj.addEventListener('moveend', updateScale)// 将比例尺添加到地图容器const mapContainer = mapObj.getContainer()mapContainer.appendChild(scaleContainer)// 保存引用以便清理customScaleControl = scaleContainer
    }/*** 比例尺配置说明:* * 通过修改 mapOptions.scaleUnit 来控制比例尺显示单位:* - 'Km': 显示公里/米(1km范围内使用米,超过1km使用公里)* - 'mi': 显示英里/英尺(1km范围内使用英里/英尺,超过1km使用英里)* - 'both': 同时显示公里/米和英里/英尺* * 通过修改 mapOptions.scaleUnitDisplay 来控制单位显示方式:* - 'word': 显示英文单词(km, m, mi, ft)* - 'chinese': 显示汉字(公里, 米, 英里, 英尺)* - 'both': 显示双语言(km/公里, m/米, mi/英里, ft/英尺)* * 比例尺长度单位:* - 1km范围内:500m, 300m, 200m, 100m, 50m, 30m, 20m, 10m, 1m* - 超过1km:按原来逻辑显示(1000km, 100km, 10km, 1km等)* * 示例:* mapOptions.scaleUnit = 'mi'  // 切换到英里显示* mapOptions.scaleUnit = 'both' // 显示双单位* mapOptions.scaleUnitDisplay = 'chinese' // 切换到汉字显示* mapOptions.scaleUnitDisplay = 'both' // 显示双语言* * 比例尺会自动显示在地图左下角,无需额外操作*/// 全屏切换
    function toggleFullscreen() {const el = document.getElementById('tianditu-map')?.parentElementif (!el) returnif (!isFullscreen.value) {if (el.requestFullscreen) el.requestFullscreen()else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen()else if (el.mozRequestFullScreen) el.mozRequestFullScreen()else if (el.msRequestFullscreen) el.msRequestFullscreen()isFullscreen.value = true} else {if (document.exitFullscreen) document.exitFullscreen()else if (document.webkitExitFullscreen) document.webkitExitFullscreen()else if (document.mozCancelFullScreen) document.mozCancelFullScreen()else if (document.msExitFullscreen) document.msExitFullscreen()isFullscreen.value = false}
    }// 监听全屏状态变化
    document.addEventListener('fullscreenchange', () => {isFullscreen.value = !!document.fullscreenElement
    })// 搜索相关函数
    function highlightKeyword(text, keyword) {if (!keyword) return textconst reg = new RegExp(`(${keyword})`, 'gi')return text.replace(reg, '<span class="search-highlight">$1</span>')
    }function getPoiIcon(catalog) {if (!catalog) return h(Location)if (catalog.includes('地铁')) return h(Promotion)if (catalog.includes('公交')) return h(Guide)if (catalog.includes('火车站') || catalog.includes('高铁')) return h(Place)if (catalog.includes('学校')) return h(School)return h(Location)
    }async function fetchSearchSuggestions(query, cb) {if (!query) { cb([]); return }const url = `https://api.tianditu.gov.cn/search?postStr={\"keyWord\":\"${encodeURIComponent(query)}\",\"level\":\"9\",\"queryType\":\"1\",\"start\":0,\"count\":10}&type=query&tk=${TIANDITU_KEY}`try {const res = await fetch(url)const data = await res.json()if (data && data.pois && Array.isArray(data.pois)) {cb(data.pois.map(item => ({value: item.name,address: item.address,catalog: item.catalog,lon: item.lonlat.split(' ')[0],lat: item.lonlat.split(' ')[1]})))} else {cb([])}} catch { cb([]) }
    }function handleSelectSuggestion(item) {if (item.lon && item.lat && mapObj) {mapObj.centerAndZoom(new window.T.LngLat(item.lon, item.lat), 16)// 添加高亮markerconst marker = new window.T.Marker(new window.T.LngLat(item.lon, item.lat))mapObj.addOverLay(marker)// 弹窗显示详细信息const popupContent = `<div style='min-width:180px;'><h4 style='margin:0 0 8px 0;'>${item.value}</h4><div style='font-size:13px;color:#666;margin-bottom:6px;'>${item.catalog || ''}</div><div style='font-size:12px;color:#999;margin-bottom:8px;'>${item.address || ''}</div><div style='font-size:12px;color:#999;'>坐标: ${item.lat}, ${item.lon}</div></div>`const infoWin = new window.T.InfoWindow(popupContent, { offset: new window.T.Pixel(0, -20) })mapObj.openInfoWindow(infoWin, new window.T.LngLat(item.lon, item.lat))ElMessage.success('已定位到:' + item.value)}
    }// 动态加载天地图API
    function loadTiandituScript() {return new Promise((resolve, reject) => {if (window.T) {resolve()return}const script = document.createElement('script')script.src = `https://api.tianditu.gov.cn/api?v=4.0&tk=${TIANDITU_KEY}`script.onload = resolvescript.onerror = rejectdocument.head.appendChild(script)})
    }// 初始化地图
    async function initMap() {await loadTiandituScript()await nextTick()if (!window.T) {ElMessage.error('天地图API加载失败')return}mapObj = new window.T.Map('tianditu-map')mapObj.centerAndZoom(new window.T.LngLat(116.4074, 39.9042), 12)mapObj.enableScrollWheelZoom()mapObj.enableDoubleClickZoom()mapObj.enableKeyboard()// 添加控件if (mapOptions.showZoom) {const zoomCtrl = new window.T.Control.Zoom({ position: window.T_ANCHOR_BOTTOM_RIGHT })mapObj.addControl(zoomCtrl)}// 添加控件 (图层切换)if (mapOptions.showLayerSwitch) {mapTypeControl = new window.T.Control.MapType()mapObj.addControl(mapTypeControl)}// 添加自定义比例尺if (mapOptions.showScale) {createCustomScale()}// 地图点击事件mapObj.addEventListener('click', onMapClick)
    }// 地图点击事件
    function onMapClick(e) {markerForm.value.lat = e.latlng.getLat().toFixed(6)markerForm.value.lng = e.latlng.getLng().toFixed(6)showMarkerForm.value = true
    }// 标记相关函数
    function saveMarker() {if (!markerForm.value.name || !markerForm.value.lat || !markerForm.value.lng) {ElMessage.warning('请填写完整信息')return}const markerData = {id: Date.now(),name: markerForm.value.name,lat: parseFloat(markerForm.value.lat),lng: parseFloat(markerForm.value.lng),description: markerForm.value.description}markers.value.push(markerData)addMarkerToMap(markerData)showMarkerForm.value = falseElMessage.success('标记保存成功')
    }function addMarkerToMap(markerData) {if (!window.T) returnconst marker = new window.T.Marker(new window.T.LngLat(markerData.lng, markerData.lat))marker.data = markerDatamarker.addEventListener('click', (e) => {showMarkerPopup(e, markerData)})mapObj.addOverLay(marker)markerObjs.push(marker)markerData._marker = marker
    }function showMarkerPopup(e, markerData) {const popupContent = `<div style='min-width:180px;'><h4 style='margin:0 0 8px 0;'>${markerData.name}</h4><div style='font-size:13px;color:#666;margin-bottom:6px;'>${markerData.description || ''}</div><div style='font-size:12px;color:#999;margin-bottom:8px;'>坐标: ${markerData.lat.toFixed(6)}, ${markerData.lng.toFixed(6)}</div><div style='display:flex;gap:8px;'><button onclick="window.tdtNavigate(${markerData.lat},${markerData.lng},'${markerData.name}')" style='background:#409EFF;color:#fff;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;'>导航</button><button onclick="navigator.clipboard.writeText('${markerData.lat},${markerData.lng}')" style='background:#67C23A;color:#fff;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;'>复制坐标</button></div></div>`const infoWin = new window.T.InfoWindow(popupContent, { offset: new window.T.Pixel(0, -20) })mapObj.openInfoWindow(infoWin, new window.T.LngLat(markerData.lng, markerData.lat))
    }function cancelMarker() {showMarkerForm.value = falsemarkerForm.value = {name: '',lat: '',lng: '',description: ''}
    }function centerOnMarker(marker) {if (mapObj) {mapObj.centerAndZoom(new window.T.LngLat(marker.lng, marker.lat), 16)ElMessage.success('已定位到标记')}
    }function navigateToMarker(marker) {window.tdtNavigate(marker.lat, marker.lng, marker.name)
    }async function removeMarker(index) {const marker = markers.value[index]try {await ElMessageBox.confirm('确定要删除这个标记吗?', '警告', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'})if (marker._marker) {mapObj.removeOverLay(marker._marker)const i = markerObjs.indexOf(marker._marker)if (i !== -1) markerObjs.splice(i, 1)}markers.value.splice(index, 1)ElMessage.success('标记已删除')} catch {}
    }async function searchLocation() {if (!searchKeyword.value.trim()) {ElMessage.warning('请输入地名')return}searchLoading.value = trueconst url = `https://api.tianditu.gov.cn/geocoder?ds={"keyWord":"${encodeURIComponent(searchKeyword.value)}"}&tk=${TIANDITU_KEY}`try {const res = await fetch(url)const data = await res.json()if (data && data.location) {const { lon, lat } = data.locationmapObj.centerAndZoom(new window.T.LngLat(lon, lat), 16)ElMessage.success('已定位到:' + searchKeyword.value)} else {ElMessage.warning('未找到地名')}} catch {ElMessage.error('地名搜索失败')}searchLoading.value = false
    }// 导航跳转函数(全局)
    window.tdtNavigate = function(lat, lng, name) {const url = `https://map.tianditu.gov.cn/navigation.html?lat=${lat}&lng=${lng}&name=${encodeURIComponent(name)}`window.open(url, '_blank')
    }// 生命周期
    onMounted(async () => {await initMap()
    })onUnmounted(() => {if (mapObj) {markerObjs.forEach(marker => mapObj.removeOverLay(marker))markerObjs.length = 0if (customScaleControl) {customScaleControl.remove()customScaleControl = null}mapObj = null}if (window.tdtNavigate) delete window.tdtNavigate
    })
    </script><style scoped>
    .tianditu-map-container {position: relative;padding: 0;max-width: 100vw;height: 50vh;background: #f5f7fa;
    }.map-top-bar {position: absolute;top: 10px;left: 10px;z-index: 500;display: flex;flex-direction: row;align-items: center;
    }.search-weather-box {display: flex;align-items: center;background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0,0,0,0.08);padding: 8px 16px;gap: 16px;
    }.search-box-official {background: #fff;border: 1px solid #dcdfe6;box-shadow: 0 2px 8px rgba(0,0,0,0.08);border-radius: 8px;padding: 0;
    }.search-input {width: 340px;font-size: 15px;border-radius: 8px;border: none;box-shadow: none;
    }.map-toolbar-top-right {position: absolute;top: 16px;right: 120px;z-index: 500;display: flex;flex-direction: row;gap: 8px;
    }.map-container {width: 100%;height: 100%;border-radius: 0;overflow: hidden;border: none;margin: 0;
    }.marker-form {position: absolute;left: 50px;top: 80px;z-index: 30;background: var(--el-bg-color-page);padding: 20px;border-radius: 8px;border: 1px solid var(--el-border-color-light);
    }.markers-list {position: absolute;right: 32px;bottom: 32px;z-index: 30;background: var(--el-bg-color-page);padding: 20px;border-radius: 8px;border: 1px solid var(--el-border-color-light);max-width: 400px;max-height: 300px;overflow: auto;
    }.markers-list h4 {margin-bottom: 15px;color: var(--el-color-primary);
    }.search-suggestion-item {display: flex;align-items: center;padding: 6px 12px;border-radius: 6px;transition: background 0.2s;cursor: pointer;
    }.search-suggestion-item.is-active,
    .search-suggestion-item:hover {background: #f0f7ff;
    }.search-suggestion-icon {margin-right: 8px;color: #409EFF;font-size: 18px;display: flex;align-items: center;
    }.search-suggestion-title {font-weight: 500;color: #222;margin-right: 8px;
    }.search-suggestion-type {color: #aaa;font-size: 13px;margin-left: 8px;margin-right: 8px;
    }.search-suggestion-meta {color: #999;font-size: 13px;flex: 1;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
    }.search-highlight {color: #409EFF;background: #e6f7ff;border-radius: 2px;padding: 0 2px;
    }</style>

完结。

http://www.dtcms.com/a/336383.html

相关文章:

  • 集运业务突围:三大关键问题的智能化解决方案
  • 【数据结构与算法-Day 16】队列的应用:广度优先搜索(BFS)的基石与迷宫寻路实战
  • vulnhub-lampiao靶机渗透
  • 002.Redis 配置及数据类型
  • 安装pytorch3d后报和本机cuda不符
  • LLM、RAG、Agent知识点思维导图
  • 简单了解BeanFactory和FactoryBean的区别
  • AMBA-AXI and ACE协议详解(八)
  • Critic-V: VLM Critics Help Catch VLM Errors in Multimodal Reasoning(CVPR 2025)
  • C++零拷贝网络编程实战:从理论到生产环境的性能优化之路
  • Word和Excel的一些功能记录
  • PHP现代化全栈开发:测试驱动开发与持续交付实践
  • 重温k8s基础概念知识系列二(Pod)
  • 腾讯开源:视频生成框架Hunyuan-GameCraft
  • 说一下事件传播机制
  • LeeCode 39.组合总和
  • 第4章 鼎鼎大名的Reactor模式
  • Redis--day7--黑马点评--优惠券秒杀
  • steam_api64.dll丢失?steam_api64.dll修复工具
  • 837. 新 21 点
  • C语言基础:(十六)深入理解指针(6)
  • 在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
  • 基于粒子群优化算法优化支持向量机的数据回归预测 PSO-SVM
  • Java实战:数字转中文大写金额的完整实现与优化技巧
  • 偏最小二乘结构方程(PLS-SEM)_TomatoSCI分析日记
  • bash shell 入门
  • rt-thread audio框架移植stm32 adc+dac,对接cherryusb uac,进行录音和播放
  • RTC之神奇小闹钟
  • 弱类型语言(Strong Typing)与强类型语言(Weak Typing)(描述语言对变量类型处理的严格程度)
  • 【Virtual Globe 渲染技术笔记】7 GPU 光线投射