#javascript #canvas
Добрый день, может ли кто то подсказать как такое как на картинке можно нарисовать
в canvas-е. План здания я нарисовал, теперь нужно сделать концентрические круги, что
приставляют мощность сигнала, и там где стена, сигнал ухудшается сильнее и соответственно
меняется цвет
Есть точка от которой расходятся концентрические круги, возле точки сигнал 100% и
постипенно он падает до 0,
пускай каждый круг шириной 2px равен 1% сигнала. Стена глушит приблизитльно на 40%.
Все ето нада визуализировать
приблизительно так:
Здесь я нарисовал план помещения и будущую точку доступа
var canvas = document.querySelector("#myCanvas");
var context = canvas.getContext('2d');
//------------------------------------- определяем координаты курсора, //для передвижения
нашей точки доступа
var canvasPos = getPosition(canvas);
var mouseX = 100;
var mouseY = 100;
function getPosition(el) {
var xPosition = 0;
var yPosition = 0;
while (el) {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition
};
}
function setMousePosition(e) {
mouseX = e.clientX - canvasPos.x;
mouseY = e.clientY - canvasPos.y;
}
canvas.onmousedown = function move() {
canvas.addEventListener("mousemove", setMousePosition, false);
};
canvas.onmouseup = function() {
canvas.removeEventListener("mousemove", setMousePosition, false);
};
//-------------------------------------- создаю функцию для рисованния //плана помещения
var img = new Image();
var imageData;
img.src = "https://s31.postimg.cc/w37y6uza3/plan1.png";
function imageOnLoad() {
context.drawImage(img, 0, 0);
//console.log(context.getImageData(0,0, img.width, img.height));
}
//-------------------------------------
function update() { // рисую план, и точку доступа
var circleRadius = 10;
context.clearRect(0, 0, canvas.width, canvas.height);
imageOnLoad();
context.beginPath();
context.arc(mouseX, mouseY, circleRadius, 0, 2 * Math.PI, true);
context.fillStyle = 'red';
context.fill();
context.closePath();
requestAnimationFrame(update);
}
update();
А здесь пробовал реализовать смену цвета, только не кругом а квадратами просто для
наглядности (работает только в одну сторону)
var canvas = document.querySelector("#myCanvas");
var context = canvas.getContext('2d');
var canvasPos = getPosition(canvas);
var mouseX = 100;
var mouseY = 100;
//-------------------------------- определяем координаты курсора, для передвижения
function getPosition(el) {
var xPosition = 0;
var yPosition = 0;
while (el) {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition
};
}
function setMousePosition(e) {
mouseX = e.clientX - canvasPos.x;
mouseY = e.clientY - canvasPos.y;
}
canvas.onmousedown = function move () {
canvas.addEventListener("mousemove", setMousePosition, false);
};
canvas.onmouseup = function () {
canvas.removeEventListener("mousemove", setMousePosition, false);
};
//-----------------------------------
let colorObj = { //создаю объект с цветами
100: [255, 51, 53, 255],
90: [255, 51, 52, 255],
80: [255, 51, 51, 255],
70: [255, 255, 53, 255],
60: [255, 255, 52, 255],
50: [255, 255, 51, 255],
40: [113, 255, 53, 255],
30: [113, 255, 52, 255],
20: [113, 255, 51, 255],
10: [51, 150, 255, 255],
0: [51, 255, 243, 255]
};
function update() {
context.clearRect(0, 0, canvas.width, canvas.height);
//----------------------- рисую линию-стену
context.beginPath();
context.lineWidth = 2;
context.moveTo(300 ,100);
context.lineTo(300 ,300);
context.stroke();
//-----------------------
//------------------------ рисую набор разноцветных квадратов
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[100][0] + ',' + colorObj[100][1] +
',' + colorObj[100][2] + ',' + colorObj[100][3] + ')';
context.fillRect(mouseX,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[90][0] + ',' + colorObj[90][1] + ','
+ colorObj[90][2] + ',' + colorObj[90][3] + ')';
context.fillRect(mouseX + 10 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[80][0] + ',' + colorObj[80][1] + ','
+ colorObj[80][2] + ',' + colorObj[80][3] + ')';
context.fillRect(mouseX + 20 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[70][0] + ',' + colorObj[70][1] + ',' +
colorObj[70][2] + ',' + colorObj[70][3] + ')';
context.fillRect(mouseX + 30 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[60][0] + ',' + colorObj[60][1] + ','
+ colorObj[60][2] + ',' + colorObj[60][3] + ')';
context.fillRect(mouseX + 40 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[50][0] + ',' + colorObj[50][1] + ',' +
colorObj[50][2] + ',' + colorObj[50][3] + ')';
context.fillRect(mouseX + 50 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[40][0] + ',' + colorObj[40][1] + ','
+ colorObj[40][2] + ',' + colorObj[40][3] + ')';
context.fillRect(mouseX + 60 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[30][0] + ',' + colorObj[30][1] + ',' +
colorObj[30][2] + ',' + colorObj[30][3] + ')';
context.fillRect(mouseX + 70 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[20][0] + ',' + colorObj[20][1] + ',' +
colorObj[20][2] + ',' + colorObj[20][3] + ')';
context.fillRect(mouseX + 80 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[10][0] + ',' + colorObj[10][1] + ',' +
colorObj[10][2] + ',' + colorObj[10][3] + ')';
context.fillRect(mouseX + 90 ,mouseY,10,10);
context.closePath();
context.beginPath();
context.fillStyle = 'rgb(' + colorObj[0][0] + ',' + colorObj[0][1] + ',' + colorObj[0][2]
+ ',' + colorObj[0][3] + ')';
context.fillRect(mouseX + 100 ,mouseY,10,10);
context.closePath();
// ----------------------------------------------------------------------
var imgData = context.getImageData(300,100,2,200);// узаню цвета пикселей в данной
области
for (let i=0;i
Ответы
Ответ 1
const canvas = document.querySelector("#myCanvas");
const context = canvas.getContext('2d');
//------------------------------------- определяем координаты курсора, для передвижения
нашей точки доступа
const canvasPos = getPosition(canvas);
let mouseX = 100;
let mouseY = 100;
function getPosition(el) {
var xPosition = 0;
var yPosition = 0;
while (el) {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition
};
}
function setMousePosition(e) {
mouseX = e.clientX - canvasPos.x;
mouseY = e.clientY - canvasPos.y;
}
canvas.onmousedown = () => canvas.addEventListener("mousemove", setMousePosition,
false);
canvas.onmouseup = () => canvas.removeEventListener("mousemove", setMousePosition,
false);
// Стенки должны лежать в таком виде, в котором их можно посчитать, картинка не подойдёт.
// Можете попробовать читать её попиксельно, но вопрос не об этом, так что.
const walls = [
//x, y, w, h
[50, 50, 1, 100],
[115, 80, 1, 40],
[125, 90, 1, 20],
[150, 50, 1, 100],
[50, 170, 100, 1],
];
// От начала к концу идут цвета от самого мощного сигнала до самого слабого.
// Один круг отображает падение сигнала == (100/длинну этого массива)%
const colors = [
'black',
'#ff0000',
'#ff0000',
'#ff3300',
'#ff6600',
'#ff9900',
'#ffcc00',
'#ffff00',
'#ccff00',
'#99ff00',
'#66ff33',
'#33ff66',
'#00ffcc',
'#00ffff',
];
// Вспомогательные функции и константа
const EPS = 1e-9;
const det = (a, b, c, d) => a * d - b * c; // детерминант
const between = (a, b, c) => Math.min(a,b) <= c + EPS && c <= Math.max(a,b) + EPS;
// проверяет лежит ли c между b и a
const intersect_1 = (a, b, c, d) => Math.max(a,c) <= Math.min(b,d);// проверяет,
пересекаются ли a-b и c-d
// Функция получает на входе координаты двух отрезков, а на выходе bool - пересекаются
они или нет.
function intersection(x11, y11, x12, y12, x21, y21, x22, y22){
// Упорядочим координаты
if(x21 > x22) [x21, x22] = [x22, x21];
if(y21 > x22) [y21, y22] = [y22, y21];
// Это я стырил.
// Тут вычисляются параметры прямой вида Ax+By+C = 0 для обоих отрезков
const A1 = y11-y12;
const B1 = x12-x11;
const C1 = -A1*x11 - B1*y11;
const A2 = y21-y22;
const B2 = x22-x21;
const C2 = -A2*x21 - B2*y21;
// Магия аналитической геометрии
var zn = det (A1, B1, A2, B2);
if (zn != 0) {
const x = -det(C1, B1, C2, B2) / zn;
const y = -det(A1, C1, A2, C2) / zn;
return between (x11, x12, x) && between (y11, y12, y)
&& between (x21, x22, x) && between (y21, y22, y);
}else
return det (A1, C1, A2, C2) == 0 && det (B1, C1, B2, C2) == 0
&& intersect_1 (x11, x12, x21, x22) && intersect_1 (y11, y12, y21, y22);
// математика, царица наук.
}
//-------------------------------------
// рисую план, и точку доступа
(function update() {
context.clearRect(0, 0, canvas.width, canvas.height);
// Рисуем стенки:
context.fillStyle = 'black';
walls.forEach(wall => context.fillRect(...wall));
// Рисуем точку:
context.fillStyle = 'red';
context.beginPath();
context.arc(mouseX, mouseY, 8, 0, 2 * Math.PI, true);
context.fill();
context.closePath();
// А теперь самое интересное.
// Будем рисовать круги маленькими дугами размера
const dA = .05;
// Потери на одной стенке - 4 * (100/colors.length) %
const signal_down = 4;
// Цикл кругов
for(let i = 1; i <= colors.length; i++){
// Цикл дуг i-ого круга
for(let alpha = 0; alpha < Math.PI*2; alpha += dA){
// Координаты конца радиуса от точки к началу дуги
const radX = mouseX + 10*i*Math.cos(alpha);
const radY = mouseY + 10*i*Math.sin(alpha);
// Считаем, сколько между нами и точкой стенок.
// Для каждой стенки проверяем, пересекается ли она с радиусом.
const wallcount = walls.filter(wall => intersection(
// Это отрезок - стенка
wall[0], wall[1], wall[0]+wall[2], wall[1]+wall[3],
// Это отрезок - радиус окружности
mouseX, mouseY, radX, radY
)).length;
// Ищем цвет для получившейся мощности. Чем ближе к концу colors тем ниже
мощность
const color = colors[i - 1 + wallcount*signal_down];
// Если сигнал еще не пропал совсем - рисуем.
if(color){
context.beginPath();
context.strokeStyle = color;
context.arc(mouseX, mouseY, i*10, alpha, alpha + dA);
context.stroke();
context.closePath();
}
}
}
requestAnimationFrame(update);
})();
Комментариев нет:
Отправить комментарий