Рисование в canvas

257
16 мая 2018, 10:10

Добрый день, может ли кто то подсказать как такое как на картинке можно нарисовать в 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<imgData.data.length;i+=4)
    {// проверяю, если цвет в етой области поменялся, меняю его на другой
        if(imgData.data[i] === 51 && imgData.data[i+1] === 255 && imgData.data[i+2] === 243 && imgData.data[i+3] === 255 ){
            colorObj[0] = [255, 255, 255, 0];
        } else if (imgData.data[i] === 51 && imgData.data[i+1] === 150 && imgData.data[i+2] === 255 && imgData.data[i+3] === 255){
            colorObj[10] = [255, 255, 255, 0];
        } else if (imgData.data[i] === 113 && imgData.data[i+1] === 255 && imgData.data[i+2] === 51 && imgData.data[i+3] === 255){
            colorObj[20] = [255, 255, 255, 0];
        } else if (imgData.data[i] === 113 && imgData.data[i+1] === 255 && imgData.data[i+2] === 52 && imgData.data[i+3] === 255){
            colorObj[30] = [51, 255, 243, 255];
        } else if (imgData.data[i] === 113 && imgData.data[i+1] === 255 && imgData.data[i+2] === 53 && imgData.data[i+3] === 255){
            colorObj[40] = [51, 150, 255, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 255 && imgData.data[i+2] === 51 && imgData.data[i+3] === 255){
            colorObj[50] = [113, 255, 51, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 255 && imgData.data[i+2] === 52 && imgData.data[i+3] === 255){
            colorObj[60] = [113, 255, 52, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 255 && imgData.data[i+2] === 53 && imgData.data[i+3] === 255){
            colorObj[70] = [113, 255, 53, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 51 && imgData.data[i+2] === 51 && imgData.data[i+3] === 255){
            colorObj[80] = [255, 255, 51, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 51 && imgData.data[i+2] === 52 && imgData.data[i+3] === 255){
            colorObj[90] = [255, 255, 52, 255];
        } else if (imgData.data[i] === 255 && imgData.data[i+1] === 51 && imgData.data[i+2] === 53 && imgData.data[i+3] === 255){
            colorObj[100] = [255, 255, 53, 255];
        }
    }
    requestAnimationFrame(update);
}
update();

Сначала думал разделить все круги на четыре сектора и по-пиксельно рисовать каждый используя формулы для полярной системы координат, но так не точно по пикселях рисует, и сильно систему нагружает.

    var circleRadius = 10;
    var r = circleRadius+1;
    var R = circleRadius + 100;
    while (r < R){
       var Fi = Math.PI/180;
       while (Fi <= (Math.PI/2)){
           context.beginPath();
           var x = mouseX;
           var y = mouseY;
           var startAngle = 0;
           var endAngle = Fi;
           context.arc(x, y, r, startAngle, endAngle, false);
           var xPolarn = r*Math.cos(Fi);
           var YPolarn = r*Math.sin(Fi);
           var xDecart = mouseX + xPolarn ;
           var yDecart = mouseY + YPolarn ;
           context.strokeStyle = 'white';
           context.stroke();
           context.closePath();
           context.beginPath();
           context.fillStyle = 'black';
           context.rect(xDecart, yDecart, 1, 1);
           context.fill();
           Fi += Math.PI/180; //+1 deg
           if(Fi < 1) {
               //Fi = 1;
           }
       }
       r += 1;
    }
Answer 1

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 = () => 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], 
]; 
 
const colors = [ 
'black', 
'#ff0000', 
'#ff0000', 
'#ff3300', 
'#ff6600', 
'#ff9900', 
'#ffcc00', 
'#ffff00', 
'#ccff00', 
'#99ff00', 
'#66ff33', 
'#33ff66', 
'#00ffcc', 
'#00ffff', 
]; 
 
// const between = (a, b, c) => (a >= b && a <= c); 
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; 
const intersect_1 = (a, b, c, d) => Math.max(a,c) <= Math.min(b,d); 
  
// pt a, pt b, pt c, pt d 
function intersection(x11, y11, x12, y12, x21, y21, x22, y22){ 
  // Упорядочим координаты 
  if(x21 > x22) [x21, x22] = [x22, x21]; 
  if(y21 > x22) [y21, y22] = [y22, y21]; 
 
  // Это я стырил 
  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; 
    for(let i = 1; i <= 14; i++){ 
		for(let alpha = 0; alpha < Math.PI*2; alpha += dA){ 
			radX = mouseX + 10*i*Math.cos(alpha); 
			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; 
			 
			// Если сигнал еще не пропал совсем - рисуем. 
			if(colors[i + wallcount*4]){ 
				context.beginPath(); 
				context.strokeStyle = colors[i - 1 + wallcount*4]; 
				context.arc(mouseX, mouseY, i*10, alpha, alpha + dA); 
				context.stroke(); 
				context.closePath(); 
			}			 
		} 
    } 
 
    requestAnimationFrame(update); 
} 
update();
<canvas id="myCanvas" width="600" height="520" style="border:1px solid #d3d3d3;"> 
Your browser does not support the HTML5 canvas tag. 
</canvas>

READ ALSO