
px转rpx跟rpx转px
1.如果是rpx转px。则调用uni.upx2px()即可
- 如果是px转rpx,公式为:rpx = px / uni.getSystemInfoSync().windowWidth * 750
1.如果是rpx转px。则调用uni.upx2px()即可
- 如果是px转rpx,公式为:rpx = px / uni.getSystemInfoSync().windowWidth * 750

canvasToTempFilePath 在h5端生成的base64 bug
HBuilderx最新版本canvas h5端生成的base64无法用 uniapp自带的image组件访问 会报net::ERR_INVALID_URL
解决方法:把image组件改成img标签就ok了
HBuilderx最新版本canvas h5端生成的base64无法用 uniapp自带的image组件访问 会报net::ERR_INVALID_URL
解决方法:把image组件改成img标签就ok了

接口请求在androidApp端很慢 大概有ios的十倍
ios、h5均正常,只有androidApp端有这个问题。同一个接口 同一个wifi下
ios、h5均正常,只有androidApp端有这个问题。同一个接口 同一个wifi下

微信小程序动态获取标题栏高度
之前开发小程序的时候,切换页面的时候,发现在IOS和安卓上,自定义标题栏和微信自带的高度不一样。
后来花了一个下午的时间,终于写出兼容的代码。当然在真机上是没有问题的。在微信开发工具模拟器上会出现不一样的问题,这个问题不大。
下面是代码 , CustomBar 代表标题栏加状态栏的高度,HeaderBar 代表 标题栏的高度
uni.getSystemInfo({
success: e => {
let StatusBar = e.statusBarHeight;
let rect = wx.getMenuButtonBoundingClientRect();
if (e.system.toLowerCase().indexOf('ios') > -1) {
//IOS
let CustomBar = rect.bottom + (rect.top - e.statusBarHeight) * 2;
let HeaderBar = CustomBar - e.statusBarHeight;
} else {
//安卓
let HeaderBar = rect.height + (rect.top - e.statusBarHeight) * 2;
let CustomBar = HeaderBar + e.statusBarHeight;
}
}
});
之前开发小程序的时候,切换页面的时候,发现在IOS和安卓上,自定义标题栏和微信自带的高度不一样。
后来花了一个下午的时间,终于写出兼容的代码。当然在真机上是没有问题的。在微信开发工具模拟器上会出现不一样的问题,这个问题不大。
下面是代码 , CustomBar 代表标题栏加状态栏的高度,HeaderBar 代表 标题栏的高度
uni.getSystemInfo({
success: e => {
let StatusBar = e.statusBarHeight;
let rect = wx.getMenuButtonBoundingClientRect();
if (e.system.toLowerCase().indexOf('ios') > -1) {
//IOS
let CustomBar = rect.bottom + (rect.top - e.statusBarHeight) * 2;
let HeaderBar = CustomBar - e.statusBarHeight;
} else {
//安卓
let HeaderBar = rect.height + (rect.top - e.statusBarHeight) * 2;
let CustomBar = HeaderBar + e.statusBarHeight;
}
}
});
收起阅读 »

分享一下iOS苹果上架App Store审核被拒4.3的解决方案,亲测有效
最近一年多的时间,苹果审核越来越严格。4.3是经常遇到的问题之一,今天给大家分享一下遇到4.3的解决方案。
1、4.3一般会有2种情况,想要快速解决就得弄清楚自己的属于哪一种情况
(1)代码相似(一般会被机审直接打回)
(2)应用与提交到App Store的其他应用相同的功能集(一般是人审4.3);
针对上面的2种回复去辨别属于哪一种情况。还有一个方式是可以查看自己APP进入审核的时间和被打回来的时间间隔,如果时间太短的可以确定是机审无疑。
针对机审4.3的修改方案
1、选择APP中的其中2个Tab做板式的变更,最好是首页+另一个Tab
2、修改UI、Icon、启动页、五图
3、修改工程名 、修改类名前缀 、文件夹文件名。
4、更换提交账户、IP、打包电脑、测试账户最好也可以更换一下
基本上以上的几个操作可以解决4.3的问题
还有网上还有许多要加垃圾代码或者混淆代码进去的方式在2019年后已经不适用,现在苹果机审已经非常强大,如果有不相信的同学可以亲身体验一下。苹果爸爸会毫不犹豫的给你打回来一个2.3.1。亲测有效,哈哈哈!
人审4.3的修改方案
如果是人工打回来的4.3,只能通过沟通去解决了。之前的解决方式是详细说明每一个页面包含哪一些具体的功能,还有自己的APP和其他APP的优势在哪一些地方。最好可以提供一下APP的使用视频,如果有软著什么的最好也一起丢给苹果吧。
楼主的提审方案就是——有什么资料都丢过去,不管苹果需不需要,以防万一。
上面的方法是已经被楼主证实过确定可行的方案(20年9月之前),目前用同一套代码上过3个APP,其他的马甲数个。
后面还有会陆续分享其他条款的解决方案。
另外,有需要代上架App Store的可以联系我代上架App,专业解决各种被拒问题:
联系方式,QQ:1481983952

最近一年多的时间,苹果审核越来越严格。4.3是经常遇到的问题之一,今天给大家分享一下遇到4.3的解决方案。
1、4.3一般会有2种情况,想要快速解决就得弄清楚自己的属于哪一种情况
(1)代码相似(一般会被机审直接打回)
(2)应用与提交到App Store的其他应用相同的功能集(一般是人审4.3);
针对上面的2种回复去辨别属于哪一种情况。还有一个方式是可以查看自己APP进入审核的时间和被打回来的时间间隔,如果时间太短的可以确定是机审无疑。
针对机审4.3的修改方案
1、选择APP中的其中2个Tab做板式的变更,最好是首页+另一个Tab
2、修改UI、Icon、启动页、五图
3、修改工程名 、修改类名前缀 、文件夹文件名。
4、更换提交账户、IP、打包电脑、测试账户最好也可以更换一下
基本上以上的几个操作可以解决4.3的问题
还有网上还有许多要加垃圾代码或者混淆代码进去的方式在2019年后已经不适用,现在苹果机审已经非常强大,如果有不相信的同学可以亲身体验一下。苹果爸爸会毫不犹豫的给你打回来一个2.3.1。亲测有效,哈哈哈!
人审4.3的修改方案
如果是人工打回来的4.3,只能通过沟通去解决了。之前的解决方式是详细说明每一个页面包含哪一些具体的功能,还有自己的APP和其他APP的优势在哪一些地方。最好可以提供一下APP的使用视频,如果有软著什么的最好也一起丢给苹果吧。
楼主的提审方案就是——有什么资料都丢过去,不管苹果需不需要,以防万一。
上面的方法是已经被楼主证实过确定可行的方案(20年9月之前),目前用同一套代码上过3个APP,其他的马甲数个。
后面还有会陆续分享其他条款的解决方案。
另外,有需要代上架App Store的可以联系我代上架App,专业解决各种被拒问题:
联系方式,QQ:1481983952

#插件需求# 漫画APP开发,已有后端接口及前端部分开源代码,增加功能即可
https://ext.dcloud.net.cn/plugin?id=1879
基于该项目,
完善付费章节限制
完善会员功能
增加签到任务模块
414Q506Q533
联系
https://ext.dcloud.net.cn/plugin?id=1879
基于该项目,
完善付费章节限制
完善会员功能
增加签到任务模块
414Q506Q533
联系

关于直播业务的一点经验
由于公司业务需求,有视频直播这方面的需求。花了两个多月研究了一下视频直播方面的方案,分享一下经验给大家。
首先,我认为,RTMP推流不适合直播,无它,再牛逼的RTMP服务器延迟也在2秒以上,无法保证一秒以内的延迟,因而我认为RTMP只适合流媒体展现。
实际上webrtc才是直播的未来,我特意花了一个星期研究了一下webrtc,现在我已经在安卓上用MUI框架,实现了多人语音视频直播,而且主持人能够关闭某个人的麦克风,切换某个人的前后摄像头,调整某个人的画质,经过我和同事测试,在2人均使用4G的情况下,我是用电信4G,同事使用联通4G,房间服务器是移动宽带,实际测试,画面无卡顿,语音无延迟。
在3个人的情况下,当画质开高的时候,就可以看到我的电信4G,带宽达到了1.2MB/s,由于4G网速有限,同事的联通4G已经只能看到2个人的画面了。当我将所有人的画质调到320*480之后,5个人实时语音视频毫无卡顿。
但是,当我在ipad上使用MUI测试webrtc的时候,却发现,似乎不太顺利开,目前我正在测试iphone上面MUI框架对webrtc的支持情况,根据我之前的经验,应该比ipad要好一些。
总结:webrtc才是直播业务的王道,毕竟实时语音通信讲究的是0延迟,画面可以渣,但是语音不能延迟,这是底线。
啦啦啦啦啦啦。。。。。。我可以向公司交差了。。。
再多说一句,BAT真的黑啊,开源的webrtc技术,到了他们手里,收费高昂。。。。。。。。。。。。。
由于公司业务需求,有视频直播这方面的需求。花了两个多月研究了一下视频直播方面的方案,分享一下经验给大家。
首先,我认为,RTMP推流不适合直播,无它,再牛逼的RTMP服务器延迟也在2秒以上,无法保证一秒以内的延迟,因而我认为RTMP只适合流媒体展现。
实际上webrtc才是直播的未来,我特意花了一个星期研究了一下webrtc,现在我已经在安卓上用MUI框架,实现了多人语音视频直播,而且主持人能够关闭某个人的麦克风,切换某个人的前后摄像头,调整某个人的画质,经过我和同事测试,在2人均使用4G的情况下,我是用电信4G,同事使用联通4G,房间服务器是移动宽带,实际测试,画面无卡顿,语音无延迟。
在3个人的情况下,当画质开高的时候,就可以看到我的电信4G,带宽达到了1.2MB/s,由于4G网速有限,同事的联通4G已经只能看到2个人的画面了。当我将所有人的画质调到320*480之后,5个人实时语音视频毫无卡顿。
但是,当我在ipad上使用MUI测试webrtc的时候,却发现,似乎不太顺利开,目前我正在测试iphone上面MUI框架对webrtc的支持情况,根据我之前的经验,应该比ipad要好一些。
总结:webrtc才是直播业务的王道,毕竟实时语音通信讲究的是0延迟,画面可以渣,但是语音不能延迟,这是底线。
啦啦啦啦啦啦。。。。。。我可以向公司交差了。。。
再多说一句,BAT真的黑啊,开源的webrtc技术,到了他们手里,收费高昂。。。。。。。。。。。。。
收起阅读 »
(借鉴柠檬app文章)--实现彩色运动轨迹uni-app
**1.将轨迹地图部分放到hybrid->html->
文件drawmap.html
(也可以外部链接)
- 利用uni自带的webview技术,引入地图轨迹**
代码:drawmap.html--- <!DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ImageLayer</title>
<meta id="viewport" name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />
<style>
html{
font-size: 24px;
}
*{
padding: 0;
margin: 0;
//禁止移动端长按复制文本
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
body{
background: beige;
font-family:-apple-system-font,"Helvetica Neue","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
}
.map-container{
margin-top: -60px;
width: 100%;
height: 500px;
/ height: calc(100% - 9rem); /
position: absolute;
min-width: 300px;
background-color: #033447;
background: #033447;
}
.info-box{
position: absolute;
top: 13rem;
right: 0.5rem;
background: rgba(0,0,0,0.3);
height: 2.2rem;
border-radius: 1.1rem;
line-height: 1.4;
padding-left: 0.4rem;
z-index: 999;
transition: margin 0.4s;
-webkit-transition: margin 0.4s;
}
.avatar{
width: 2rem;
height: 2rem;
float: right;
border: 0.1rem solid #fff;
border-radius: 50%;
}
.name{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
color: #fff;
font-size: 0.7rem;
margin-top: 0.3rem;
}
.time{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
font-size: 0.5rem;
color: rgba(255,255,255,0.8);
}
p{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
}
</style>
</head>
<body>
<div class="container">
<div class="info-box">
<img class="avatar" src="./img/applogo.png" alt="">
<p class="name">app名称</p>
<p class="time" id="time">09月10日</p>
</div>
<div id="map-container" class="map-container"></div>
</div>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=高德key值"></script>
<script>
var pointsList = [];
function getNowFormatDate() {
var date = new Date();
var seperator1 = "月";
var month = date.getMonth() + 1;//月
var strDate = date.getDate(); //日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = month + seperator1 + strDate + '日';
document.getElementById("time").innerHTML = currentdate
// return currentdate;
}
getNowFormatDate();
// 从地址栏中获取训练id;查询
var reg = new RegExp("(^|&)"+ 'userid' +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
// console.log(unescape(r[2]));
// var index=window.location.search.fiIndexOf("\-");
// obj=obj.substring(index+1,obj.length);
var url = '请求经纬度的接口/getDynamicTrack?userid='+unescape(r[2])
// 请球数据
function getData(url){
// console.log("调用"+url)
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.send();
/**
* 获取数据后的处理程序
*/
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;//获取到json字符串,还需解析
pointsList = JSON.parse(json).data;
// console.log(pointsList);
preProcessList();
setCustomLayer();
}
};
}
getData(url);
var mapZooms = [3, 18]
var map = new AMap.Map('map-container', {
mapStyle: 'https://amap://styles/blue',
resizeEnable: true, //是否监控地图容器尺寸变化
dragEnable: false, //地图是否可通过鼠标拖拽平移,
doubleClickZoom: false, //地图是否可通过双击鼠标放大地图
keyboardEnable: false, // 地图是否可通过键盘控制,默认为true方向键控制地图平移,
scrollWheel: false, // 地图是否可通过鼠标滚轮缩放浏览
touchZoom: false, // 地图在移动终端上是否可通过多点触控缩放浏览地图
zooms: mapZooms
});
map.setFeatures(['bg','road']); // 多个种类要素显示
// 监听容器变化
// map.on('zoomend', function(ev) {
// console.log('缩放等级变化了-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// setCustomLayer();
// });
// map.on('click', function(ev) {
// console.log('鼠标点击-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('moveend', function(ev) {
// console.log('地图中心点变化-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('touchend', function(ev) {
// console.log('手机触摸-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom());
// setCustomLayer();
// });
// 获取经纬度(这里处理数据)--start
/*
* 添加Canvas图层
*/
var polylineArr = [];
var colorSteps = 10; // 颜色等级
var maxSpeed = 0;
var minSpeed = 0;
var averageSpeed = 0; // 平均速度
var totalSpeed = 0;
// setAvgSpeed();
var speedTopStep = 0;
var speedBellowStep = 0;
function setPoints(){
var makers = [];
var markersArg = [{
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-start.png',
position: [pointsList[0].longitude, pointsList[0].latitude]
}, {
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-end.png',
position: [pointsList[pointsList.length-1].longitude, pointsList[pointsList.length-1].latitude]
}];
markersArg.forEach(function(marker) {
var maker = new AMap.Marker({
map: map,
position: [marker.position[0], marker.position[1]],
icon: new AMap.Icon({
size: new AMap.Size(20, 20), //图标大小
image: marker.icon,
imageSize: new AMap.Size(20,20)
}),
offset: new AMap.Pixel(-10, -10)
});
});
}
function preProcessList() {
for (var i = 0; i < pointsList.length; i++) {
var tmp = [];
var speed = pointsList[i].speed;
tmp[0] = pointsList[i].longitude;
tmp[1] = pointsList[i].latitude;
// 数组累加求平均data.reduce((totalPrice, item) => totalPrice + item.price, 0);
totalSpeed += speed
polylineArr.push(tmp);
// 获取最高速度和最低速度
if (speed > -1 && speed > maxSpeed) {
maxSpeed = speed;
}
if (speed > -1 && speed < minSpeed) {
minSpeed = speed;
}
}
averageSpeed = totalSpeed/pointsList.length;
// console.log('平均速度'+averageSpeed)
speedTopStep = (maxSpeed - averageSpeed) / colorSteps;
speedBellowStep = (averageSpeed - minSpeed) / colorSteps;
// console.log('最大速度颜色等级'+speedTopStep)
// console.log('最小速度颜色等级'+speedBellowStep)
/** 使用高德地图自带的覆盖方法, 自动定位并缩放, 但不显示-start **/
// console.log('开始定位和自适应屏幕')
var polyline = new AMap.Polyline({
path: polylineArr,
strokeColor: "#FF33FF", // //线颜色
strokeOpacity: 0,
strokeWeight: 0,
zIndex:0
});
polyline.setMap(map);
// 绘制开始点和结束点
setPoints();
// setPoints(); // 绘制标记点--每1公里标记一下
map.setFitView(); //屏幕自适应-// 自动适配到合适视野范围// 无参数,默认包括所有覆盖物的情况
/* end */
// console.log('结束定位和自适应屏幕')
}
// 绘制标记点
/* end */
/* 不同颜色的轨迹-start */
// 处理颜色的方法
var bellowColors = ["#ffff00", "#fff500", "#ffe800", "#ffd900", "#ffc700", "#ffb400", "#ffa000", "#ff8a00", "#ff6000", "#ff2700", "#ff0000"];
var topColors = ["#ffff00", "#eeff00", "#d7ff00", "#bcff00", "#9fff00", "#7fff00", "#5fff00", "#41ff00", "#27ff00", "#10ff00", "#00ff00"];
function getColor(speed) {
if(speed < 0 ){
return '#ffff00';
}
var subSpeed = speed - averageSpeed;
if (subSpeed > 0) {
if(speedTopStep===0){
return topColors[10];
}
var level = parseInt(subSpeed / speedTopStep);
// console.log('等级'+level)
return topColors[level];
} else {
if(speedBellowStep===0){
return topColors[10];
}
var level = parseInt(Math.abs(subSpeed) / speedBellowStep);
return bellowColors[level];
}
}
// 初始化canvas
var canvas = '';
function setCustomLayer() {
// console.log('初始化canvas')
// CustomLayer类(插件)--自定义图层
map.plugin(['AMap.CustomLayer'], function () {
canvas = document.createElement('canvas');
var customLayer = new AMap.CustomLayer(canvas, {
zIndex: 99,
zooms: map.getZoom()
});
customLayer.setMap(map); // 设置图层所属的地图对象,传入null时从当前地图移除
customLayer.render = drawLine(); // 初始化完成时候,开发者需要给该图层设定render方法,该方法需要实现图层的绘制,API会在合适的时机自动调用该方法
});
}
// setTimeout(function(){
// }, 3000);
// 绘制
function drawLine() {
console.log('开始绘制轨迹')
var context = canvas.getContext('2d');// 一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。
canvas.width = map.getSize().width;
canvas.height = map.getSize().height;
context.globalAlpha=1; // 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
context.clearRect(0, 0, canvas.width, canvas.height); //(x, y, widh, height)清除指定的矩形区域,然后这块区域会变的完全透明。 再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法
context.lineWidth = 3; // 线宽。只能是正值。默认是1.0。
context.lineCap = 'round'; // 线条末端样式。(butt:线段末端以方形结束;round:线段末端以圆形结束;square:线段末端以方形结束,)
// 遍历所有的点
var startColor = '';
var endColor = '';
// 第一个点
pointsList[0].containerPos = map.lngLatToContainer([pointsList[0].longitude, pointsList[0].latitude]);
for (var j = 1, pointLen = pointsList.length; j < pointLen; j++) {
pointsList[j].containerPos = map.lngLatToContainer([pointsList[j].longitude, pointsList[j].latitude]); // 转换为地图识别的格式
var startX = pointsList[j - 1].containerPos.x; //开始点的x坐标
var startY = pointsList[j - 1].containerPos.y; //开始点的y坐标
var endX = pointsList[j].containerPos.x; //结束点的x坐标
var endY = pointsList[j].containerPos.y; //结束点的y坐标
context.beginPath(); // 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
context.moveTo(startX, startY); // 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
context.lineTo(endX, endY); // //绘制一条从当前位置到指定坐标(200, 50)的直线.
context.strokeStyle = getColor(pointsList[j].speed); //根据速度来获取颜色---设置图形轮廓的颜色
context.stroke(); // 通过线条来绘制图形轮廓
//设置渐变
startColor = getColor(pointsList[j-1].speed);
endColor = getColor(pointsList[j].speed);
var grd = context.createLinearGradient(startX, startY, endX, endY); // 创建线性的渐变对象
grd.addColorStop(0, startColor);
grd.addColorStop(1, endColor);
context.strokeStyle = grd;
context.stroke();
}
}
/* end */
</script>
</body>
</html>
4.finsh.vue页面引入
// #ifdef APP-PLUS
wv = plus.webview.create("","custom-webview",{
plusrequire:"none",
'uni-app': 'none',
top: 0 ,
height: 400,
})
wv.loadURL("/hybrid/html/drawmap.html?userid="+that.userId)
var currentWebview = this.$scope.$getAppWebview();
currentWebview.append(wv);
setTimeout(function() {
// console.log(wv.getStyle())
}, 1000);
// #endif
**1.将轨迹地图部分放到hybrid->html->
文件drawmap.html
(也可以外部链接)
- 利用uni自带的webview技术,引入地图轨迹**
代码:drawmap.html--- <!DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ImageLayer</title>
<meta id="viewport" name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />
<style>
html{
font-size: 24px;
}
*{
padding: 0;
margin: 0;
//禁止移动端长按复制文本
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
body{
background: beige;
font-family:-apple-system-font,"Helvetica Neue","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
}
.map-container{
margin-top: -60px;
width: 100%;
height: 500px;
/ height: calc(100% - 9rem); /
position: absolute;
min-width: 300px;
background-color: #033447;
background: #033447;
}
.info-box{
position: absolute;
top: 13rem;
right: 0.5rem;
background: rgba(0,0,0,0.3);
height: 2.2rem;
border-radius: 1.1rem;
line-height: 1.4;
padding-left: 0.4rem;
z-index: 999;
transition: margin 0.4s;
-webkit-transition: margin 0.4s;
}
.avatar{
width: 2rem;
height: 2rem;
float: right;
border: 0.1rem solid #fff;
border-radius: 50%;
}
.name{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
color: #fff;
font-size: 0.7rem;
margin-top: 0.3rem;
}
.time{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
font-size: 0.5rem;
color: rgba(255,255,255,0.8);
}
p{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
}
</style>
</head>
<body>
<div class="container">
<div class="info-box">
<img class="avatar" src="./img/applogo.png" alt="">
<p class="name">app名称</p>
<p class="time" id="time">09月10日</p>
</div>
<div id="map-container" class="map-container"></div>
</div>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=高德key值"></script>
<script>
var pointsList = [];
function getNowFormatDate() {
var date = new Date();
var seperator1 = "月";
var month = date.getMonth() + 1;//月
var strDate = date.getDate(); //日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = month + seperator1 + strDate + '日';
document.getElementById("time").innerHTML = currentdate
// return currentdate;
}
getNowFormatDate();
// 从地址栏中获取训练id;查询
var reg = new RegExp("(^|&)"+ 'userid' +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
// console.log(unescape(r[2]));
// var index=window.location.search.fiIndexOf("\-");
// obj=obj.substring(index+1,obj.length);
var url = '请求经纬度的接口/getDynamicTrack?userid='+unescape(r[2])
// 请球数据
function getData(url){
// console.log("调用"+url)
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.send();
/**
* 获取数据后的处理程序
*/
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;//获取到json字符串,还需解析
pointsList = JSON.parse(json).data;
// console.log(pointsList);
preProcessList();
setCustomLayer();
}
};
}
getData(url);
var mapZooms = [3, 18]
var map = new AMap.Map('map-container', {
mapStyle: 'https://amap://styles/blue',
resizeEnable: true, //是否监控地图容器尺寸变化
dragEnable: false, //地图是否可通过鼠标拖拽平移,
doubleClickZoom: false, //地图是否可通过双击鼠标放大地图
keyboardEnable: false, // 地图是否可通过键盘控制,默认为true方向键控制地图平移,
scrollWheel: false, // 地图是否可通过鼠标滚轮缩放浏览
touchZoom: false, // 地图在移动终端上是否可通过多点触控缩放浏览地图
zooms: mapZooms
});
map.setFeatures(['bg','road']); // 多个种类要素显示
// 监听容器变化
// map.on('zoomend', function(ev) {
// console.log('缩放等级变化了-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// setCustomLayer();
// });
// map.on('click', function(ev) {
// console.log('鼠标点击-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('moveend', function(ev) {
// console.log('地图中心点变化-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('touchend', function(ev) {
// console.log('手机触摸-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom());
// setCustomLayer();
// });
// 获取经纬度(这里处理数据)--start
/*
* 添加Canvas图层
*/
var polylineArr = [];
var colorSteps = 10; // 颜色等级
var maxSpeed = 0;
var minSpeed = 0;
var averageSpeed = 0; // 平均速度
var totalSpeed = 0;
// setAvgSpeed();
var speedTopStep = 0;
var speedBellowStep = 0;
function setPoints(){
var makers = [];
var markersArg = [{
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-start.png',
position: [pointsList[0].longitude, pointsList[0].latitude]
}, {
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-end.png',
position: [pointsList[pointsList.length-1].longitude, pointsList[pointsList.length-1].latitude]
}];
markersArg.forEach(function(marker) {
var maker = new AMap.Marker({
map: map,
position: [marker.position[0], marker.position[1]],
icon: new AMap.Icon({
size: new AMap.Size(20, 20), //图标大小
image: marker.icon,
imageSize: new AMap.Size(20,20)
}),
offset: new AMap.Pixel(-10, -10)
});
});
}
function preProcessList() {
for (var i = 0; i < pointsList.length; i++) {
var tmp = [];
var speed = pointsList[i].speed;
tmp[0] = pointsList[i].longitude;
tmp[1] = pointsList[i].latitude;
// 数组累加求平均data.reduce((totalPrice, item) => totalPrice + item.price, 0);
totalSpeed += speed
polylineArr.push(tmp);
// 获取最高速度和最低速度
if (speed > -1 && speed > maxSpeed) {
maxSpeed = speed;
}
if (speed > -1 && speed < minSpeed) {
minSpeed = speed;
}
}
averageSpeed = totalSpeed/pointsList.length;
// console.log('平均速度'+averageSpeed)
speedTopStep = (maxSpeed - averageSpeed) / colorSteps;
speedBellowStep = (averageSpeed - minSpeed) / colorSteps;
// console.log('最大速度颜色等级'+speedTopStep)
// console.log('最小速度颜色等级'+speedBellowStep)
/** 使用高德地图自带的覆盖方法, 自动定位并缩放, 但不显示-start **/
// console.log('开始定位和自适应屏幕')
var polyline = new AMap.Polyline({
path: polylineArr,
strokeColor: "#FF33FF", // //线颜色
strokeOpacity: 0,
strokeWeight: 0,
zIndex:0
});
polyline.setMap(map);
// 绘制开始点和结束点
setPoints();
// setPoints(); // 绘制标记点--每1公里标记一下
map.setFitView(); //屏幕自适应-// 自动适配到合适视野范围// 无参数,默认包括所有覆盖物的情况
/* end */
// console.log('结束定位和自适应屏幕')
}
// 绘制标记点
/* end */
/* 不同颜色的轨迹-start */
// 处理颜色的方法
var bellowColors = ["#ffff00", "#fff500", "#ffe800", "#ffd900", "#ffc700", "#ffb400", "#ffa000", "#ff8a00", "#ff6000", "#ff2700", "#ff0000"];
var topColors = ["#ffff00", "#eeff00", "#d7ff00", "#bcff00", "#9fff00", "#7fff00", "#5fff00", "#41ff00", "#27ff00", "#10ff00", "#00ff00"];
function getColor(speed) {
if(speed < 0 ){
return '#ffff00';
}
var subSpeed = speed - averageSpeed;
if (subSpeed > 0) {
if(speedTopStep===0){
return topColors[10];
}
var level = parseInt(subSpeed / speedTopStep);
// console.log('等级'+level)
return topColors[level];
} else {
if(speedBellowStep===0){
return topColors[10];
}
var level = parseInt(Math.abs(subSpeed) / speedBellowStep);
return bellowColors[level];
}
}
// 初始化canvas
var canvas = '';
function setCustomLayer() {
// console.log('初始化canvas')
// CustomLayer类(插件)--自定义图层
map.plugin(['AMap.CustomLayer'], function () {
canvas = document.createElement('canvas');
var customLayer = new AMap.CustomLayer(canvas, {
zIndex: 99,
zooms: map.getZoom()
});
customLayer.setMap(map); // 设置图层所属的地图对象,传入null时从当前地图移除
customLayer.render = drawLine(); // 初始化完成时候,开发者需要给该图层设定render方法,该方法需要实现图层的绘制,API会在合适的时机自动调用该方法
});
}
// setTimeout(function(){
// }, 3000);
// 绘制
function drawLine() {
console.log('开始绘制轨迹')
var context = canvas.getContext('2d');// 一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。
canvas.width = map.getSize().width;
canvas.height = map.getSize().height;
context.globalAlpha=1; // 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
context.clearRect(0, 0, canvas.width, canvas.height); //(x, y, widh, height)清除指定的矩形区域,然后这块区域会变的完全透明。 再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法
context.lineWidth = 3; // 线宽。只能是正值。默认是1.0。
context.lineCap = 'round'; // 线条末端样式。(butt:线段末端以方形结束;round:线段末端以圆形结束;square:线段末端以方形结束,)
// 遍历所有的点
var startColor = '';
var endColor = '';
// 第一个点
pointsList[0].containerPos = map.lngLatToContainer([pointsList[0].longitude, pointsList[0].latitude]);
for (var j = 1, pointLen = pointsList.length; j < pointLen; j++) {
pointsList[j].containerPos = map.lngLatToContainer([pointsList[j].longitude, pointsList[j].latitude]); // 转换为地图识别的格式
var startX = pointsList[j - 1].containerPos.x; //开始点的x坐标
var startY = pointsList[j - 1].containerPos.y; //开始点的y坐标
var endX = pointsList[j].containerPos.x; //结束点的x坐标
var endY = pointsList[j].containerPos.y; //结束点的y坐标
context.beginPath(); // 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
context.moveTo(startX, startY); // 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
context.lineTo(endX, endY); // //绘制一条从当前位置到指定坐标(200, 50)的直线.
context.strokeStyle = getColor(pointsList[j].speed); //根据速度来获取颜色---设置图形轮廓的颜色
context.stroke(); // 通过线条来绘制图形轮廓
//设置渐变
startColor = getColor(pointsList[j-1].speed);
endColor = getColor(pointsList[j].speed);
var grd = context.createLinearGradient(startX, startY, endX, endY); // 创建线性的渐变对象
grd.addColorStop(0, startColor);
grd.addColorStop(1, endColor);
context.strokeStyle = grd;
context.stroke();
}
}
/* end */
</script>
</body>
</html>
4.finsh.vue页面引入
// #ifdef APP-PLUS
wv = plus.webview.create("","custom-webview",{
plusrequire:"none",
'uni-app': 'none',
top: 0 ,
height: 400,
})
wv.loadURL("/hybrid/html/drawmap.html?userid="+that.userId)
var currentWebview = this.$scope.$getAppWebview();
currentWebview.append(wv);
setTimeout(function() {
// console.log(wv.getStyle())
}, 1000);
// #endif
收起阅读 »

uni仿keep跑步彩色运动轨迹,--利用高德自带的API + H5的canvas(借鉴柠檬-很感谢)
**1.将轨迹地图部分放到hybrid->html->文件drawmap.html(也可以外部链接)
- 利用uni自带的webview技术,引入地图轨迹**
代码:
drawmap.html---<!DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ImageLayer</title>
<meta id="viewport" name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />
<style>
html{
font-size: 24px;
}
{
padding: 0;
margin: 0;
//禁止移动端长按复制文本
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
body{
background: beige;
font-family:-apple-system-font,"Helvetica Neue","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
}
.map-container{
margin-top: -60px;
width: 100%;
height: 500px;
/ height: calc(100% - 9rem); */
position: absolute;
min-width: 300px;
background-color: #033447;
background: #033447;
}
.info-box{
position: absolute;
top: 13rem;
right: 0.5rem;
background: rgba(0,0,0,0.3);
height: 2.2rem;
border-radius: 1.1rem;
line-height: 1.4;
padding-left: 0.4rem;
z-index: 999;
transition: margin 0.4s;
-webkit-transition: margin 0.4s;
}
.avatar{
width: 2rem;
height: 2rem;
float: right;
border: 0.1rem solid #fff;
border-radius: 50%;
}
.name{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
color: #fff;
font-size: 0.7rem;
margin-top: 0.3rem;
}
.time{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
font-size: 0.5rem;
color: rgba(255,255,255,0.8);
}
p{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
}
</style>
</head>
<body>
<div class="container">
<div class="info-box">
<img class="avatar" src="./img/applogo.png" alt="">
<p class="name">app名称</p>
<p class="time" id="time">09月10日</p>
</div>
<div id="map-container" class="map-container"></div>
</div>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=8af5729787cab8a4b5930a9b20d141bc"></script>
<script>
var pointsList = [];
function getNowFormatDate() {
var date = new Date();
var seperator1 = "月";
var month = date.getMonth() + 1;//月
var strDate = date.getDate(); //日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = month + seperator1 + strDate + '日';
document.getElementById("time").innerHTML = currentdate
// return currentdate;
}
getNowFormatDate();
// 从地址栏中获取训练id;查询
var reg = new RegExp("(^|&)"+ 'userid' +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
// console.log(unescape(r[2]));
// var index=window.location.search.fiIndexOf("\-");
// obj=obj.substring(index+1,obj.length);
var url = '请求经纬度的接口/getDynamicTrack?userid='+unescape(r[2])
// 请球数据
function getData(url){
// console.log("调用"+url)
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.send();
/**
* 获取数据后的处理程序
*/
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;//获取到json字符串,还需解析
pointsList = JSON.parse(json).data;
// console.log(pointsList);
preProcessList();
setCustomLayer();
}
};
}
getData(url);
var mapZooms = [3, 18]
var map = new AMap.Map('map-container', {
mapStyle: 'https://amap://styles/blue',
resizeEnable: true, //是否监控地图容器尺寸变化
dragEnable: false, //地图是否可通过鼠标拖拽平移,
doubleClickZoom: false, //地图是否可通过双击鼠标放大地图
keyboardEnable: false, // 地图是否可通过键盘控制,默认为true方向键控制地图平移,
scrollWheel: false, // 地图是否可通过鼠标滚轮缩放浏览
touchZoom: false, // 地图在移动终端上是否可通过多点触控缩放浏览地图
zooms: mapZooms
});
map.setFeatures(['bg','road']); // 多个种类要素显示
// 监听容器变化
// map.on('zoomend', function(ev) {
// console.log('缩放等级变化了-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// setCustomLayer();
// });
// map.on('click', function(ev) {
// console.log('鼠标点击-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('moveend', function(ev) {
// console.log('地图中心点变化-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('touchend', function(ev) {
// console.log('手机触摸-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom());
// setCustomLayer();
// });
// 获取经纬度(这里处理数据)--start
/*
* 添加Canvas图层
*/
var polylineArr = [];
var colorSteps = 10; // 颜色等级
var maxSpeed = 0;
var minSpeed = 0;
var averageSpeed = 0; // 平均速度
var totalSpeed = 0;
// setAvgSpeed();
var speedTopStep = 0;
var speedBellowStep = 0;
function setPoints(){
var makers = [];
var markersArg = [{
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-start.png',
position: [pointsList[0].longitude, pointsList[0].latitude]
}, {
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-end.png',
position: [pointsList[pointsList.length-1].longitude, pointsList[pointsList.length-1].latitude]
}];
markersArg.forEach(function(marker) {
var maker = new AMap.Marker({
map: map,
position: [marker.position[0], marker.position[1]],
icon: new AMap.Icon({
size: new AMap.Size(20, 20), //图标大小
image: marker.icon,
imageSize: new AMap.Size(20,20)
}),
offset: new AMap.Pixel(-10, -10)
});
});
}
function preProcessList() {
for (var i = 0; i < pointsList.length; i++) {
var tmp = [];
var speed = pointsList[i].speed;
tmp[0] = pointsList[i].longitude;
tmp[1] = pointsList[i].latitude;
// 数组累加求平均data.reduce((totalPrice, item) => totalPrice + item.price, 0);
totalSpeed += speed
polylineArr.push(tmp);
// 获取最高速度和最低速度
if (speed > -1 && speed > maxSpeed) {
maxSpeed = speed;
}
if (speed > -1 && speed < minSpeed) {
minSpeed = speed;
}
}
averageSpeed = totalSpeed/pointsList.length;
// console.log('平均速度'+averageSpeed)
speedTopStep = (maxSpeed - averageSpeed) / colorSteps;
speedBellowStep = (averageSpeed - minSpeed) / colorSteps;
// console.log('最大速度颜色等级'+speedTopStep)
// console.log('最小速度颜色等级'+speedBellowStep)
/** 使用高德地图自带的覆盖方法, 自动定位并缩放, 但不显示-start **/
// console.log('开始定位和自适应屏幕')
var polyline = new AMap.Polyline({
path: polylineArr,
strokeColor: "#FF33FF", // //线颜色
strokeOpacity: 0,
strokeWeight: 0,
zIndex:0
});
polyline.setMap(map);
// 绘制开始点和结束点
setPoints();
// setPoints(); // 绘制标记点--每1公里标记一下
map.setFitView(); //屏幕自适应-// 自动适配到合适视野范围// 无参数,默认包括所有覆盖物的情况
/* end */
// console.log('结束定位和自适应屏幕')
}
// 绘制标记点
/* end */
/* 不同颜色的轨迹-start */
// 处理颜色的方法
var bellowColors = ["#ffff00", "#fff500", "#ffe800", "#ffd900", "#ffc700", "#ffb400", "#ffa000", "#ff8a00", "#ff6000", "#ff2700", "#ff0000"];
var topColors = ["#ffff00", "#eeff00", "#d7ff00", "#bcff00", "#9fff00", "#7fff00", "#5fff00", "#41ff00", "#27ff00", "#10ff00", "#00ff00"];
function getColor(speed) {
if(speed < 0 ){
return '#ffff00';
}
var subSpeed = speed - averageSpeed;
if (subSpeed > 0) {
if(speedTopStep===0){
return topColors[10];
}
var level = parseInt(subSpeed / speedTopStep);
// console.log('等级'+level)
return topColors[level];
} else {
if(speedBellowStep===0){
return topColors[10];
}
var level = parseInt(Math.abs(subSpeed) / speedBellowStep);
return bellowColors[level];
}
}
// 初始化canvas
var canvas = '';
function setCustomLayer() {
// console.log('初始化canvas')
// CustomLayer类(插件)--自定义图层
map.plugin(['AMap.CustomLayer'], function () {
canvas = document.createElement('canvas');
var customLayer = new AMap.CustomLayer(canvas, {
zIndex: 99,
zooms: map.getZoom()
});
customLayer.setMap(map); // 设置图层所属的地图对象,传入null时从当前地图移除
customLayer.render = drawLine(); // 初始化完成时候,开发者需要给该图层设定render方法,该方法需要实现图层的绘制,API会在合适的时机自动调用该方法
});
}
// setTimeout(function(){
// }, 3000);
// 绘制
function drawLine() {
console.log('开始绘制轨迹')
var context = canvas.getContext('2d');// 一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。
canvas.width = map.getSize().width;
canvas.height = map.getSize().height;
context.globalAlpha=1; // 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
context.clearRect(0, 0, canvas.width, canvas.height); //(x, y, widh, height)清除指定的矩形区域,然后这块区域会变的完全透明。 再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法
context.lineWidth = 3; // 线宽。只能是正值。默认是1.0。
context.lineCap = 'round'; // 线条末端样式。(butt:线段末端以方形结束;round:线段末端以圆形结束;square:线段末端以方形结束,)
// 遍历所有的点
var startColor = '';
var endColor = '';
// 第一个点
pointsList[0].containerPos = map.lngLatToContainer([pointsList[0].longitude, pointsList[0].latitude]);
for (var j = 1, pointLen = pointsList.length; j < pointLen; j++) {
pointsList[j].containerPos = map.lngLatToContainer([pointsList[j].longitude, pointsList[j].latitude]); // 转换为地图识别的格式
var startX = pointsList[j - 1].containerPos.x; //开始点的x坐标
var startY = pointsList[j - 1].containerPos.y; //开始点的y坐标
var endX = pointsList[j].containerPos.x; //结束点的x坐标
var endY = pointsList[j].containerPos.y; //结束点的y坐标
context.beginPath(); // 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
context.moveTo(startX, startY); // 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
context.lineTo(endX, endY); // //绘制一条从当前位置到指定坐标(200, 50)的直线.
context.strokeStyle = getColor(pointsList[j].speed); //根据速度来获取颜色---设置图形轮廓的颜色
context.stroke(); // 通过线条来绘制图形轮廓
//设置渐变
startColor = getColor(pointsList[j-1].speed);
endColor = getColor(pointsList[j].speed);
var grd = context.createLinearGradient(startX, startY, endX, endY); // 创建线性的渐变对象
grd.addColorStop(0, startColor);
grd.addColorStop(1, endColor);
context.strokeStyle = grd;
context.stroke();
}
}
/* end */
</script>
</body>
</html>
4.finsh.vue页面引入
// #ifdef APP-PLUS
wv = plus.webview.create("","custom-webview",{
plusrequire:"none",
'uni-app': 'none',
top: 0 ,
height: 400,
})
wv.loadURL("/hybrid/html/drawmap.html?userid="+that.userId)
var currentWebview = this.$scope.$getAppWebview();
currentWebview.append(wv);
setTimeout(function() {
// console.log(wv.getStyle())
}, 1000);
// #endif
**1.将轨迹地图部分放到hybrid->html->文件drawmap.html(也可以外部链接)
- 利用uni自带的webview技术,引入地图轨迹**
代码:
drawmap.html---<!DOCTYPE html> <html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ImageLayer</title>
<meta id="viewport" name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />
<style>
html{
font-size: 24px;
}
{
padding: 0;
margin: 0;
//禁止移动端长按复制文本
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
body{
background: beige;
font-family:-apple-system-font,"Helvetica Neue","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
}
.map-container{
margin-top: -60px;
width: 100%;
height: 500px;
/ height: calc(100% - 9rem); */
position: absolute;
min-width: 300px;
background-color: #033447;
background: #033447;
}
.info-box{
position: absolute;
top: 13rem;
right: 0.5rem;
background: rgba(0,0,0,0.3);
height: 2.2rem;
border-radius: 1.1rem;
line-height: 1.4;
padding-left: 0.4rem;
z-index: 999;
transition: margin 0.4s;
-webkit-transition: margin 0.4s;
}
.avatar{
width: 2rem;
height: 2rem;
float: right;
border: 0.1rem solid #fff;
border-radius: 50%;
}
.name{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
color: #fff;
font-size: 0.7rem;
margin-top: 0.3rem;
}
.time{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
font-size: 0.5rem;
color: rgba(255,255,255,0.8);
}
p{
padding-right: 2.5rem;
white-space: nowrap;
text-align: right;
}
</style>
</head>
<body>
<div class="container">
<div class="info-box">
<img class="avatar" src="./img/applogo.png" alt="">
<p class="name">app名称</p>
<p class="time" id="time">09月10日</p>
</div>
<div id="map-container" class="map-container"></div>
</div>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=8af5729787cab8a4b5930a9b20d141bc"></script>
<script>
var pointsList = [];
function getNowFormatDate() {
var date = new Date();
var seperator1 = "月";
var month = date.getMonth() + 1;//月
var strDate = date.getDate(); //日
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = month + seperator1 + strDate + '日';
document.getElementById("time").innerHTML = currentdate
// return currentdate;
}
getNowFormatDate();
// 从地址栏中获取训练id;查询
var reg = new RegExp("(^|&)"+ 'userid' +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
// console.log(unescape(r[2]));
// var index=window.location.search.fiIndexOf("\-");
// obj=obj.substring(index+1,obj.length);
var url = '请求经纬度的接口/getDynamicTrack?userid='+unescape(r[2])
// 请球数据
function getData(url){
// console.log("调用"+url)
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.send();
/**
* 获取数据后的处理程序
*/
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;//获取到json字符串,还需解析
pointsList = JSON.parse(json).data;
// console.log(pointsList);
preProcessList();
setCustomLayer();
}
};
}
getData(url);
var mapZooms = [3, 18]
var map = new AMap.Map('map-container', {
mapStyle: 'https://amap://styles/blue',
resizeEnable: true, //是否监控地图容器尺寸变化
dragEnable: false, //地图是否可通过鼠标拖拽平移,
doubleClickZoom: false, //地图是否可通过双击鼠标放大地图
keyboardEnable: false, // 地图是否可通过键盘控制,默认为true方向键控制地图平移,
scrollWheel: false, // 地图是否可通过鼠标滚轮缩放浏览
touchZoom: false, // 地图在移动终端上是否可通过多点触控缩放浏览地图
zooms: mapZooms
});
map.setFeatures(['bg','road']); // 多个种类要素显示
// 监听容器变化
// map.on('zoomend', function(ev) {
// console.log('缩放等级变化了-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// setCustomLayer();
// });
// map.on('click', function(ev) {
// console.log('鼠标点击-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('moveend', function(ev) {
// console.log('地图中心点变化-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom())
// });
// map.on('touchend', function(ev) {
// console.log('手机触摸-----------')
// console.log(map.getSize().width)
// console.log(map.getSize().height)
// console.log('获取地图等级'+map.getZoom());
// setCustomLayer();
// });
// 获取经纬度(这里处理数据)--start
/*
* 添加Canvas图层
*/
var polylineArr = [];
var colorSteps = 10; // 颜色等级
var maxSpeed = 0;
var minSpeed = 0;
var averageSpeed = 0; // 平均速度
var totalSpeed = 0;
// setAvgSpeed();
var speedTopStep = 0;
var speedBellowStep = 0;
function setPoints(){
var makers = [];
var markersArg = [{
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-start.png',
position: [pointsList[0].longitude, pointsList[0].latitude]
}, {
icon: 'http://statics.oulafen.com/h5_draw_map_color/image/point-end.png',
position: [pointsList[pointsList.length-1].longitude, pointsList[pointsList.length-1].latitude]
}];
markersArg.forEach(function(marker) {
var maker = new AMap.Marker({
map: map,
position: [marker.position[0], marker.position[1]],
icon: new AMap.Icon({
size: new AMap.Size(20, 20), //图标大小
image: marker.icon,
imageSize: new AMap.Size(20,20)
}),
offset: new AMap.Pixel(-10, -10)
});
});
}
function preProcessList() {
for (var i = 0; i < pointsList.length; i++) {
var tmp = [];
var speed = pointsList[i].speed;
tmp[0] = pointsList[i].longitude;
tmp[1] = pointsList[i].latitude;
// 数组累加求平均data.reduce((totalPrice, item) => totalPrice + item.price, 0);
totalSpeed += speed
polylineArr.push(tmp);
// 获取最高速度和最低速度
if (speed > -1 && speed > maxSpeed) {
maxSpeed = speed;
}
if (speed > -1 && speed < minSpeed) {
minSpeed = speed;
}
}
averageSpeed = totalSpeed/pointsList.length;
// console.log('平均速度'+averageSpeed)
speedTopStep = (maxSpeed - averageSpeed) / colorSteps;
speedBellowStep = (averageSpeed - minSpeed) / colorSteps;
// console.log('最大速度颜色等级'+speedTopStep)
// console.log('最小速度颜色等级'+speedBellowStep)
/** 使用高德地图自带的覆盖方法, 自动定位并缩放, 但不显示-start **/
// console.log('开始定位和自适应屏幕')
var polyline = new AMap.Polyline({
path: polylineArr,
strokeColor: "#FF33FF", // //线颜色
strokeOpacity: 0,
strokeWeight: 0,
zIndex:0
});
polyline.setMap(map);
// 绘制开始点和结束点
setPoints();
// setPoints(); // 绘制标记点--每1公里标记一下
map.setFitView(); //屏幕自适应-// 自动适配到合适视野范围// 无参数,默认包括所有覆盖物的情况
/* end */
// console.log('结束定位和自适应屏幕')
}
// 绘制标记点
/* end */
/* 不同颜色的轨迹-start */
// 处理颜色的方法
var bellowColors = ["#ffff00", "#fff500", "#ffe800", "#ffd900", "#ffc700", "#ffb400", "#ffa000", "#ff8a00", "#ff6000", "#ff2700", "#ff0000"];
var topColors = ["#ffff00", "#eeff00", "#d7ff00", "#bcff00", "#9fff00", "#7fff00", "#5fff00", "#41ff00", "#27ff00", "#10ff00", "#00ff00"];
function getColor(speed) {
if(speed < 0 ){
return '#ffff00';
}
var subSpeed = speed - averageSpeed;
if (subSpeed > 0) {
if(speedTopStep===0){
return topColors[10];
}
var level = parseInt(subSpeed / speedTopStep);
// console.log('等级'+level)
return topColors[level];
} else {
if(speedBellowStep===0){
return topColors[10];
}
var level = parseInt(Math.abs(subSpeed) / speedBellowStep);
return bellowColors[level];
}
}
// 初始化canvas
var canvas = '';
function setCustomLayer() {
// console.log('初始化canvas')
// CustomLayer类(插件)--自定义图层
map.plugin(['AMap.CustomLayer'], function () {
canvas = document.createElement('canvas');
var customLayer = new AMap.CustomLayer(canvas, {
zIndex: 99,
zooms: map.getZoom()
});
customLayer.setMap(map); // 设置图层所属的地图对象,传入null时从当前地图移除
customLayer.render = drawLine(); // 初始化完成时候,开发者需要给该图层设定render方法,该方法需要实现图层的绘制,API会在合适的时机自动调用该方法
});
}
// setTimeout(function(){
// }, 3000);
// 绘制
function drawLine() {
console.log('开始绘制轨迹')
var context = canvas.getContext('2d');// 一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。
canvas.width = map.getSize().width;
canvas.height = map.getSize().height;
context.globalAlpha=1; // 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
context.clearRect(0, 0, canvas.width, canvas.height); //(x, y, widh, height)清除指定的矩形区域,然后这块区域会变的完全透明。 再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法
context.lineWidth = 3; // 线宽。只能是正值。默认是1.0。
context.lineCap = 'round'; // 线条末端样式。(butt:线段末端以方形结束;round:线段末端以圆形结束;square:线段末端以方形结束,)
// 遍历所有的点
var startColor = '';
var endColor = '';
// 第一个点
pointsList[0].containerPos = map.lngLatToContainer([pointsList[0].longitude, pointsList[0].latitude]);
for (var j = 1, pointLen = pointsList.length; j < pointLen; j++) {
pointsList[j].containerPos = map.lngLatToContainer([pointsList[j].longitude, pointsList[j].latitude]); // 转换为地图识别的格式
var startX = pointsList[j - 1].containerPos.x; //开始点的x坐标
var startY = pointsList[j - 1].containerPos.y; //开始点的y坐标
var endX = pointsList[j].containerPos.x; //结束点的x坐标
var endY = pointsList[j].containerPos.y; //结束点的y坐标
context.beginPath(); // 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
context.moveTo(startX, startY); // 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
context.lineTo(endX, endY); // //绘制一条从当前位置到指定坐标(200, 50)的直线.
context.strokeStyle = getColor(pointsList[j].speed); //根据速度来获取颜色---设置图形轮廓的颜色
context.stroke(); // 通过线条来绘制图形轮廓
//设置渐变
startColor = getColor(pointsList[j-1].speed);
endColor = getColor(pointsList[j].speed);
var grd = context.createLinearGradient(startX, startY, endX, endY); // 创建线性的渐变对象
grd.addColorStop(0, startColor);
grd.addColorStop(1, endColor);
context.strokeStyle = grd;
context.stroke();
}
}
/* end */
</script>
</body>
</html>
4.finsh.vue页面引入
// #ifdef APP-PLUS
wv = plus.webview.create("","custom-webview",{
plusrequire:"none",
'uni-app': 'none',
top: 0 ,
height: 400,
})
wv.loadURL("/hybrid/html/drawmap.html?userid="+that.userId)
var currentWebview = this.$scope.$getAppWebview();
currentWebview.append(wv);
setTimeout(function() {
// console.log(wv.getStyle())
}, 1000);
// #endif
收起阅读 »

hbuilder的几个功能细节的建议
本人使用过微软系列的vs各种, phpstrom,webstrom,notepad++,安卓as, java的eclipse 大概主流的这些吧,说这些是因为我想谦卑的希望xbuilder 能在细节上添加或者改进一下,
或许用起来更流畅,当然当前的一些功能也非常的具有其他软件没有的.
第一点: 右键 复制 剪贴 只需要这四个字就可以,有时候用右键时 ,找复制 还需要思考
哦~~这文章输入框还不能直接粘贴 qq截切过来的图.....我还是不提建议了...
还是说完吧
支持左侧拖js 文件到文档,可以把目录引用到代码里,多方便.
我看很多java 家族左侧文件名有个通病,就是点击两次不能改名,还得右键重命名,这个功能也挺不错的
千篇一律的ctrl+鼠标左键找 源头,为何hbuilder 选择用alt 加鼠标左键.
本人使用过微软系列的vs各种, phpstrom,webstrom,notepad++,安卓as, java的eclipse 大概主流的这些吧,说这些是因为我想谦卑的希望xbuilder 能在细节上添加或者改进一下,
或许用起来更流畅,当然当前的一些功能也非常的具有其他软件没有的.
第一点: 右键 复制 剪贴 只需要这四个字就可以,有时候用右键时 ,找复制 还需要思考
哦~~这文章输入框还不能直接粘贴 qq截切过来的图.....我还是不提建议了...
还是说完吧
支持左侧拖js 文件到文档,可以把目录引用到代码里,多方便.
我看很多java 家族左侧文件名有个通病,就是点击两次不能改名,还得右键重命名,这个功能也挺不错的
千篇一律的ctrl+鼠标左键找 源头,为何hbuilder 选择用alt 加鼠标左键.

关于uni.downloadFile与uni.saveFiled文件名不一,解决方案思路
uni.downloadFile 下载的文件是临时的,名字是下载文件的名字
uni.saveFiled 本地保存 ,名字是时间戳
实现缓存:如何让保存到 本地的文件 和 下载文件的原名 一样 (好像两个都不支持下载文件到指定位置和改变下载文件名)
解决方案思路
可以考虑uni.setStorageSync(本地缓存) 同时缓存两个值 当下载文件名改变时 才进行下一步操作
有好的方案 大家可以进行讨论
uni.downloadFile 下载的文件是临时的,名字是下载文件的名字
uni.saveFiled 本地保存 ,名字是时间戳
实现缓存:如何让保存到 本地的文件 和 下载文件的原名 一样 (好像两个都不支持下载文件到指定位置和改变下载文件名)
解决方案思路
可以考虑uni.setStorageSync(本地缓存) 同时缓存两个值 当下载文件名改变时 才进行下一步操作
有好的方案 大家可以进行讨论
收起阅读 »
开发者中心Unipush分组对比优化介绍
消息推送分组对比功能优化介绍
分组测试功能支持在同一个推送计划中,添加2-5条文案/人群进行对比测试,通过对各测试组的到达、展示、点击数据的监测分析,筛选出最优文案/人群,并支持实时及定时地按最优测试组补发剩余用户,提高通知消息点击率,助力运营提效。
【更新简述】
- 支持实时及定时按最优测试组补发剩余用户
- 测试分组:从最多支持2组增加到最多支持5组测试
- 页面改版,模块划分为:测试内容、推送设置、Android配置、ios配置
- 测试模式:仍旧支持“对比通知文案”和“对比用户群体”
- 测试目标平台:在支持Android的基础上,新增支持iOS
- 测试人群:在支持随机用户、标签用户、用户分组的基础上,新增支持CID用户及别名用户
- 测试推送设置:在支持设置消息有效时长、定时的基础上,新增支持定速、厂商策略
- 新增Android配置:支持设置通知渠道模板、后续动作
- 新增iOS配置:支持设置badge,sound,附加字段
- 新增测试任务管理:支持取消测试、停止测试、停止补发
备注:AB测试不适合进行大范围推送场景,为了达到精准推送的目的,每组参测人数建议大于10000人,所有组合计参测人数最大值是150000人。测试组测试人数建议相同
【更新详情】
1.支持实时及定时按最优测试组补发剩余用户
新增对分组测试的到达、展示、点击等后效数据进行实时监测分析,筛选出最优测试组,支持实时及定时的自动或手动补发,将测试得到的最佳文案/人群,推送给剩余的目标用户,优化推送的点击效果。
(1)自动补发
①根据测试的后效数据分析,自动筛选出最佳文案/人群,并直接推送给剩余的目标用户,优化推送的点击效果。
②测试的后效数据分析主要通过点击率实现:点击率=点击数/到达率。
③可设置定时补发功能,也就是设置测试消息下发后、自动补发的生效起始时间,支持15分钟-12小时。
④可设置默认文案功能,用于在多文案/人群测试中,在多文案中选择出其中一个文案作为默认文案,当出现点击率无法及时统计而导致系统无法自动选出最佳文案/人群补发时,发送默认文案。
(2)手动补发
在【数据统计】-【推送记录】-【分组测试记录】中查看分组测试的详情及效果数据,自行手动选择补发组。
(3)【测试人群】选择【CID用户】和【别名用户】时,不支持补发功能。
(4)当在【按最优测试结果补发剩余用户】选择【自动补发】或【手动补发】时,剩余用户的补发推送完成后,会在【推送记录】-【通知消息】的记录中,生成一条相应的推送记录,可查看推送详情及效果数据。
2.测试分组:从最多支持2组增加到最多支持5组测试
3.页面改版,模块划分为:测试内容、推送设置、Android配置、iOS配置
4.测试模式:仍旧支持“对比通知文案”和“对比用户群体”
(1)对比通知文案:向多组属性相似的人群推送多个不同的文案,测试哪个文案更受用户欢迎;
(2)对比用户群体:将相同的文案内容推送给多组属性不同的人群,测试该文案内容更受哪类人群欢迎。
5.测试目标平台:在支持Android的基础上,新增支持iOS
6.测试人群:在支持随机用户、标签用户、用户分组的基础上,新增支持CID用户及别名用户
7.测试推送设置:在支持设置消息有效时长、定时的基础上,新增支持定速、厂商策略
8.新增Android配置:支持设置通知渠道模板、后续动作
9.新增iOS配置:支持设置badge、sound、附加字段
10.新增测试任务管理:支持取消测试、停止测试、停止补发
(1)测试任务定时,还未开始下发测试组前,操作支持:取消测试、取消补发
(2)已下发测试任务,还未开始补发剩余用户前,操作支持:停止测试、取消补发
消息推送分组对比功能优化介绍
分组测试功能支持在同一个推送计划中,添加2-5条文案/人群进行对比测试,通过对各测试组的到达、展示、点击数据的监测分析,筛选出最优文案/人群,并支持实时及定时地按最优测试组补发剩余用户,提高通知消息点击率,助力运营提效。
【更新简述】
- 支持实时及定时按最优测试组补发剩余用户
- 测试分组:从最多支持2组增加到最多支持5组测试
- 页面改版,模块划分为:测试内容、推送设置、Android配置、ios配置
- 测试模式:仍旧支持“对比通知文案”和“对比用户群体”
- 测试目标平台:在支持Android的基础上,新增支持iOS
- 测试人群:在支持随机用户、标签用户、用户分组的基础上,新增支持CID用户及别名用户
- 测试推送设置:在支持设置消息有效时长、定时的基础上,新增支持定速、厂商策略
- 新增Android配置:支持设置通知渠道模板、后续动作
- 新增iOS配置:支持设置badge,sound,附加字段
- 新增测试任务管理:支持取消测试、停止测试、停止补发
备注:AB测试不适合进行大范围推送场景,为了达到精准推送的目的,每组参测人数建议大于10000人,所有组合计参测人数最大值是150000人。测试组测试人数建议相同
【更新详情】
1.支持实时及定时按最优测试组补发剩余用户
新增对分组测试的到达、展示、点击等后效数据进行实时监测分析,筛选出最优测试组,支持实时及定时的自动或手动补发,将测试得到的最佳文案/人群,推送给剩余的目标用户,优化推送的点击效果。
(1)自动补发
①根据测试的后效数据分析,自动筛选出最佳文案/人群,并直接推送给剩余的目标用户,优化推送的点击效果。
②测试的后效数据分析主要通过点击率实现:点击率=点击数/到达率。
③可设置定时补发功能,也就是设置测试消息下发后、自动补发的生效起始时间,支持15分钟-12小时。
④可设置默认文案功能,用于在多文案/人群测试中,在多文案中选择出其中一个文案作为默认文案,当出现点击率无法及时统计而导致系统无法自动选出最佳文案/人群补发时,发送默认文案。
(2)手动补发
在【数据统计】-【推送记录】-【分组测试记录】中查看分组测试的详情及效果数据,自行手动选择补发组。
(3)【测试人群】选择【CID用户】和【别名用户】时,不支持补发功能。
(4)当在【按最优测试结果补发剩余用户】选择【自动补发】或【手动补发】时,剩余用户的补发推送完成后,会在【推送记录】-【通知消息】的记录中,生成一条相应的推送记录,可查看推送详情及效果数据。
2.测试分组:从最多支持2组增加到最多支持5组测试
3.页面改版,模块划分为:测试内容、推送设置、Android配置、iOS配置
4.测试模式:仍旧支持“对比通知文案”和“对比用户群体”
(1)对比通知文案:向多组属性相似的人群推送多个不同的文案,测试哪个文案更受用户欢迎;
(2)对比用户群体:将相同的文案内容推送给多组属性不同的人群,测试该文案内容更受哪类人群欢迎。
5.测试目标平台:在支持Android的基础上,新增支持iOS
6.测试人群:在支持随机用户、标签用户、用户分组的基础上,新增支持CID用户及别名用户
7.测试推送设置:在支持设置消息有效时长、定时的基础上,新增支持定速、厂商策略
8.新增Android配置:支持设置通知渠道模板、后续动作
9.新增iOS配置:支持设置badge、sound、附加字段
10.新增测试任务管理:支持取消测试、停止测试、停止补发
(1)测试任务定时,还未开始下发测试组前,操作支持:取消测试、取消补发
(2)已下发测试任务,还未开始补发剩余用户前,操作支持:停止测试、取消补发