Страницы

Поиск по вопросам

понедельник, 16 декабря 2019 г.

Рисование в canvas распространения мощности сигнала

#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); })(); Your browser does not support the HTML5 canvas tag.

Комментариев нет:

Отправить комментарий