// 加载图片
export const loadImg = (src) => {
return new Promise((resolve) => {
const img = new Image();
// img.crossOrigin = 'Anonymous';
img.src = src;
img.setAttribute('crossOrigin', 'Anonymous');
img.onload = () => {
resolve(img);
};
});
};
export const getOffsetPoint = (obj) => {
// 获取某元素以浏览器左上角为原点的坐标
let y = obj.offsetTop; // 获取该元素对应父容器的上边距
let x = obj.offsetLeft; // 对应父容器的上边距
// 判断是否有父容器,如果存在则累加其边距
while (obj === obj.offsetParent) {
// 等效 obj = obj.offsetParent;while (obj != undefined)
y += obj.offsetTop; // 叠加父容器的上边距
x += obj.offsetLeft; // 叠加父容器的左边距
}
return {
x,
y
};
};
export const generateLinePoint = (event, config, containerInfo) => {
let {width, height, x, y} = containerInfo;
x = event.clientX - x;
y = event.clientY - y;
// 缩放位移坐标变化规律
// (transformOrigin - downX) / scale * (scale-1) + downX - translateX = pointX
const pointX = ((width / 2 - x) / config.scale) * (config.scale - 1) + x - config.translateX;
const pointY = ((height / 2 - y) / config.scale) * (config.scale - 1) + y - config.translateY;
return {
pointX,
pointY
};
};
// 绘制
export const drawPoint = (ctx, x, y, color, noPoint, diameter) => {
return new Promise((resolve) => {
if (Object.prototype.toString.call(x) !== '[object Number]') return false;
// 设置绘制颜色
ctx.fillStyle = color ? color : '#fb0606';
// 绘制成矩形
// ctx.arc(point.x, point.y,5, 0, Math.PI * 5);
if (diameter) {
ctx.fillRect(x - diameter / 2, y - diameter / 2, diameter, diameter);
} else {
ctx.fillRect(x - 1, y - 1, 1, 1);
}
// 设置字体样式
ctx.font = '12px bold 宋体';
// 绘制文字
noPoint ? '' : ctx.fillText(`${x.toFixed(2) / 1}, ${y.toFixed(2) / 1}`, x, y);
resolve();
});
};
export const drawLine = (ctx, prevXY, nextXY, color) => {
ctx.beginPath();
ctx.lineWidth = '1';
ctx.strokeStyle = color || 'red';
ctx.moveTo(prevXY[0], prevXY[1]);
ctx.lineTo(nextXY[0], nextXY[1]);
ctx.stroke();
};
export const drawClose = (ctx, x, y) => {
ctx.fillStyle = 'red';
ctx.font = '12px bold 宋体';
// 绘制文字
ctx.fillText('x', x, y);
};
/**
*
* lens:12焦距
* sensor_size_scale 1.8 传感器尺寸
* k1 畸变系数
*{
Eigen::Matrix3d rotationMatrix = quaternion_.toRotationMatrix();
Eigen::Vector3d p_camera = rotationMatrix.transpose() * (Point3d - t_);
double xc1 = p_camera(0, 0) / p_camera(2, 0);
double yc1 = p_camera(1, 0) / p_camera(2, 0);
double r_2 = xc1 * xc1 + yc1 * yc1;
fx_ = 2203.0 * lens * sensor_size_scale / 16.0;
fy_ = 2203.0 * lens * sensor_size_scale / 16.0;
cx_ = 960.0;
cy_ = 540.0;
double u1 = fx_ * (1 + k1 * r_2) * xc1 + cx_;
double v1 = fy_ * (1 + k1 * r_2) * yc1 + cy_;
return Eigen::Vector2d(u1, v1);
}
*/
export const formatUn3dTo2d = ([x, y, z], yamlData, row) => {
// 联合标定 3d to2d
let matrix3 = new THREE.Matrix3();
const qw = yamlData.towards[0];
const qx = yamlData.towards[1];
const qy = yamlData.towards[2];
const qz = yamlData.towards[3];
const tx = yamlData.xyz[0];
const ty = yamlData.xyz[1];
const tz = yamlData.xyz[2];
const fx = (2203.0 * row.lens * row.sensorSizeScale) / 16.0;
const fy = (2203.0 * row.lens * row.sensorSizeScale) / 16.0;
const cx = 960.0;
const cy = 540.0;
const k1 = 0; // 目前c++存在的问题 先用0 后续row.distortion
let transPose = matrix3
.set(
1 - 2 * (qy * qy) - 2 * (qz * qz),
2 * (qx * qy - qw * qz),
2 * (qx * qz + qw * qy),
2 * (qx * qy + qw * qz),
1 - 2 * (qx * qx) - 2 * (qz * qz),
2 * (qy * qz - qw * qx),
2 * (qx * qz - qw * qy),
2 * (qy * qz + qw * qx),
1 - 2 * (qx * qx) - 2 * (qy * qy)
)
.transpose();
let point3d = new THREE.Vector3(x, y, z).sub(new THREE.Vector3(tx, ty, tz));
let v = point3d.applyMatrix3(transPose);
const xc1 = v.getComponent(0) / v.getComponent(2);
const yc1 = v.getComponent(1) / v.getComponent(2);
// eslint-disable-next-line camelcase
const r_2 = xc1 * xc1 + yc1 * yc1;
// eslint-disable-next-line camelcase
return v.getComponent(2) > 0
? new THREE.Vector2(fx * (1 + k1 * r_2) * xc1 + cx, fy * (1 + k1 * r_2) * yc1 + cy)
: {x: undefined, y: undefined};
};
export const from3dTo2d = ([x, y, z], yamlData, insertResult) => {
// 外参标定 3d to2d
const qw = yamlData.towards[0];
const qx = yamlData.towards[1];
const qy = yamlData.towards[2];
const qz = yamlData.towards[3];
const tx = yamlData.xyz[0];
const ty = yamlData.xyz[1];
const tz = yamlData.xyz[2];
const fx = insertResult.internalParam[0];
const fy = insertResult.internalParam[1];
const cx = insertResult.internalParam[2];
const cy = insertResult.internalParam[3];
let matrix3 = new THREE.Matrix3();
let transPose = matrix3
.set(
1 - 2 * (qy * qy) - 2 * (qz * qz),
2 * (qx * qy - qw * qz),
2 * (qx * qz + qw * qy),
2 * (qx * qy + qw * qz),
1 - 2 * (qx * qx) - 2 * (qz * qz),
2 * (qy * qz - qw * qx),
2 * (qx * qz - qw * qy),
2 * (qy * qz + qw * qx),
1 - 2 * (qx * qx) - 2 * (qy * qy)
)
.transpose();
let point3d = new THREE.Vector3(x, y, z).sub(new THREE.Vector3(tx, ty, tz));
let v = point3d.applyMatrix3(transPose);
return v.getComponent(2) > 0
? new THREE.Vector2(
(fx * v.getComponent(0)) / v.getComponent(2) + cx,
(fy * v.getComponent(1)) / v.getComponent(2) + cy
)
: {x: undefined, y: undefined};
};
export const quaterTransEuler = (x, y, z, w) => {
const Euler = new THREE.Euler();
const quaternion = new THREE.Quaternion(x, y, z, w);
return Euler.setFromQuaternion(quaternion);
};
export const eulerTransQuater = (x, y, z) => {
const Euler = new THREE.Euler(x, y, z);
const quaternion = new THREE.Quaternion();
return quaternion.setFromEuler(Euler);
};
// img转base64
export const imgTransformBase64 = (url) => {
return new Promise((resolve) => {
const Img = new Image();
let dataURL = '';
Img.src = url;
Img.setAttribute('crossOrigin', 'Anonymous');
Img.onload = () => {
const canvas = document.createElement('canvas');
const width = Img.width;
const height = Img.height;
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(Img, 0, 0, width, height);
dataURL = canvas.toDataURL('image/jpeg');
resolve(dataURL);
};
});
};
// img 转blob--- 新增--- 另一种方法:canvas.toBlob()方法
const imgTransformBlob = async (url) => {
const blob = await fetch(url).then((res) => res.blob())
return blob
}
// 另外
export const imgTransformBlob = (url) => {
let b = null;
try {
const a = axios.create();
const result = await a({
url,
method: 'get',
responseType: 'blob'
});
b = result.data;
} catch (error) {
console.log(error);
}
return b;
// 第二种方法
return new Promise((resolve) => {
const Img = new Image()
let dataURL = ''
Img.src = url
Img.setAttribute('crossOrigin', 'Anonymous')
Img.onload = () => {
alert(4)
const canvas = document.createElement('canvas')
const width = Img.width
const height = Img.height
canvas.width = width
canvas.height = height
canvas.getContext('2d').drawImage(Img, 0, 0, width, height)
dataURL = canvas.toBlob(
(blob) => {
console.log(blob, 'blob')
resolve(blob)
},
'image/jpeg',
1
)
}
})
}
// base64转blob
export const convertBase64UrlToBlob = (urlData) => {
// 去掉url的头,并转换为byte
const split = urlData.split(',');
const bytes = window.atob(split[1]);
// 处理异常,将ascii码小于0的转换为大于0
const ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {type: split[0]});
};
// base64转file文件
export const dataURLtoFile = (dataurl, filename) => {
const arr = dataurl.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
};
// file文件/blob转base64图片
export const getBase64 = (file) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
let imgResult = '';
reader.readAsDataURL(file);
reader.onload = () => {
imgResult = reader.result;
};
reader.onerror = (error) => {
reject(error);
};
reader.onloadend = () => {
resolve(imgResult);
};
});
};
// 欧几里得距离
export const getDistance = (a, b) => {
const xDiff = (a.x - b.x) ** 2;
const yDiff = (a.y - b.y) ** 2;
return Math.sqrt(xDiff + yDiff);
};
// 查找最短距离
export const findRecentPoint = (pointList, targetPoint) => {
let sd = getDistance(pointList[0], targetPoint);
let sdItem = pointList[0];
let sdIndex = 0;
for (const [index, item] of pointList.entries()) {
const nowd = getDistance(item, targetPoint);
if (nowd < sd && !item.link) {
sd = nowd;
sdItem = item;
sdIndex = index;
}
}
return {
item: sdItem,
index: sdIndex
};
};
# 其他
// base64 转 blob
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}
# 资料
Canvas实现图片绘制、缩放、移动和保存历史状态,纯干货 (opens new window)
Base64转二进制文件流以及转File、图片转Base64、二进制流转Base64 (opens new window)