Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Canvas. Как сделать или вообще нельзя? Вращение рандомизированно изменяемого объекта. (https://javascript.ru/forum/misc/43614-canvas-kak-sdelat-ili-voobshhe-nelzya-vrashhenie-randomizirovanno-izmenyaemogo-obekta.html)

Zemsky 13.12.2013 17:42

Canvas. Как сделать или вообще нельзя? Вращение рандомизированно изменяемого объекта.
 
Как это сделать в canvas? Или вообще не получится?

Пример:
- отрисованный объект (не подгружаемый). Например, стрелка заданного размера, цвета (именно нарисованная как пятиугольник).
- ориентация "вверх-вниз-влево-вправо". 90 град. Random.
- изменение положения объекта (центра) в пределах квадрата со стороной в 2 раза больше длины объекта. Random. Шаг 10 пикселей.
- изменение размера объекта. Увеличение/уменьшение с шагом 0,1 от начального размера до в 2-е увеличенного. Random.
- таймер 1 секунда, счетчик до 10.

Т.е. стрелка каждую секунду меняет свое положение, размер и ориентацию.

Не получаются совместные вращения с перемещением центра вращения в центр рандомизированно построенного смещенного объекта. Учусь... Находил примеры для подгружаемых рисунков. Аналогия не получается.. А может и нельзя сделать? М.б. нужны библиотеки или по-другому как-то?

Faab 13.12.2013 18:32

Я тоже только учусь, но если каждую секунду воздействовать на свойства в CSS (размер, угол вращения), то может получится.. а canvas вроде для цвета, но я точно не утвеждаю.

Zemsky 13.12.2013 18:57

Вот пытаюсь:

<!DOCTYPE HTML>
<html>                                                
<head>                                                      
<script>

        setInterval(function() {

        var canvas=document.getElementById("myCanvas");
	var context=canvas.getContext("2d");
// Очистка холста        
    context.clearRect(0, 0, canvas.width, canvas.height);    
// Размеры квадрата.        
        var rectWidth = 40;
	var rectHeight = 40;          
// Расчет угла поворота по часовой стрелке
        var q1 = Math.floor((Math.round(Math.random()*10))/4);
        var q2 = Math.floor((Math.round(Math.random()*10))/4);
// Расчет смещения стимула по X и Y 	   
        var x1 = 20+Math.round((Math.random()*10));
        var y1 = 20+Math.round((Math.random()*10));
//        var x2 = 100+Math.round(Math.random()*100)/10);
//        var y2 = 100+Math.round(Math.random()*100)/10);                 

 
 
  
// Смещение начала осей координат в центр фигуры
	context.translate(canvas.width/2,canvas.height/2); 		
// Смещение фигуры
        context.translate(x1,y1);
        //context.translate(-x2,-y2);
// Поворот фигуры
        context.rotate(Math.PI/q1);
        context.rotate(Math.PI/q2);
 
// Рисование квадрата

        context.fillStyle="#ff0000";
	context.fillRect(-rectWidth/2,-rectHeight/2,rectWidth,rectHeight);
// Вставка символа
	context.font="30pt Calibri";
	context.textAlign="center";
	context.fillStyle="#0000ff";
	context.fillText("Ю",0,15); }, 200);
 
</script>
</head>
<body>
	<canvas id="myCanvas" width="400" height="400"></canvas>
</body>
</html>

Zemsky 13.12.2013 19:33

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 286518)
Пожалуйста, отформатируйте свой код!

Так сделал?

Faab 13.12.2013 20:02

Наверное он просил это (чистый JS):
setInterval(function() {

        var canvas=document.getElementById("myCanvas");
	var context=canvas.getContext("2d");
// Очистка холста        
    context.clearRect(0, 0, canvas.width, canvas.height);    
// Размеры квадрата.        
        var rectWidth = 40;
	var rectHeight = 40;          
// Расчет угла поворота по часовой стрелке
        var q1 = Math.floor((Math.round(Math.random()*10))/4);
        var q2 = Math.floor((Math.round(Math.random()*10))/4);
// Расчет смещения стимула по X и Y 	   
        var x1 = 20+Math.round((Math.random()*10));
        var y1 = 20+Math.round((Math.random()*10));
//        var x2 = 100+Math.round(Math.random()*100)/10);
//        var y2 = 100+Math.round(Math.random()*100)/10);                 

  
// Смещение начала осей координат в центр фигуры
	context.translate(canvas.width/2,canvas.height/2); 		
// Смещение фигуры
        context.translate(x1,y1);
        //context.translate(-x2,-y2);
// Поворот фигуры
        context.rotate(Math.PI/q1);
        context.rotate(Math.PI/q2);
 
// Рисование квадрата

        context.fillStyle="#ff0000";
	context.fillRect(-rectWidth/2,-rectHeight/2,rectWidth,rectHeight);
// Вставка символа
	context.font="30pt Calibri";
	context.textAlign="center";
	context.fillStyle="#0000ff";
	context.fillText("Ю",0,15); }, 200);

Zemsky 13.12.2013 21:34

Цитата:

Сообщение от Дзен-трансгуманист (Сообщение 286534)
Zemsky,

Кстати, у вас эффект всех context.translate и context.rotate будет складываться, и получится, что вся картинка через несколько кадров уедет куда-то за экран.
Перед изменениями трансформаций желательно сохранить контекст, а после рендеринга восстановить.

Спасибо. Понял. Буду пробовать.

Zemsky 18.12.2013 19:23

Попробовал сделать цикл. Чтобы значение угла поворота квадрата не повторялось подряд. В чем я ошибся?

a=0;
		
		// Первое объявление переменных для проверки неповторения значения q
		var q=0;  
		var qold=0;


	
        b=setInterval (function() {
        var canvas=document.getElementById("myCanvas");
	    var context=canvas.getContext("2d");
// Размеры квадрата.        
        var rectWidth = 40;
	    var rectHeight = 40;          
// Сохранение 
        context.save();
// Очистка холста 
        context.clearRect(0, 0, canvas.width, canvas.height);      
// Смещение начала осей координат в центр фигуры
        context.translate(canvas.width/2+Math.round((Math.random()*100)-50),canvas.height/2+Math.round((Math.random()*100)-50)); 		

		
		// Алгоритм поворота квадрата с проверкой неповторения значения q 
		
		// Расчет угла поворота по часовой стрелке
        if (q==qold) {
		q = Math.floor((Math.random()*10)/3)*0.5;}
		// Поворот  	
		context.rotate(Math.PI*q);
		qold=q;
		
		
		
// Рисование квадрата
        context.fillStyle="#ff0000";
	    context.fillRect(0,0,rectWidth,rectHeight);
// Вставка символа
	    context.font="30pt Calibri";
	    context.textAlign="center";
	    context.fillStyle="#0000ff";
	    context.fillText("W",20,33);
        a++;
        if(a==50){clearInterval(b)};
		// Восстановление
        context.restore(); 
        }, 1000);

рони 18.12.2013 19:57

Zemsky,
Вариант...
Цитата:

Сообщение от Zemsky
Чтобы значение угла поворота квадрата не повторялось подряд

<!DOCTYPE html>

<html>
<head>
  <title></title>
  <meta charset="utf-8">
</head>

<body>
  <canvas id="myCanvas" width="400" height="400"></canvas> <script>
  var a = 0;

  // Первое объявление переменных для проверки неповторения значения q
  var q = 0;
  var qold = 0;
  var b = setInterval(function () {
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    // Размеры квадрата.
    var rectWidth = 40;
    var rectHeight = 40;
    // Сохранение
    context.save();
    // Очистка холста
    context.clearRect(0, 0, canvas.width, canvas.height);
    // Смещение начала осей координат в центр фигуры
    context.translate(canvas.width / 2 + Math.round((Math.random() * 100) - 50), canvas.height / 2 + Math.round((Math.random() * 100) - 50));


    // Алгоритм поворота квадрата с проверкой неповторения значения q

    // Расчет угла поворота по часовой стрелке

    do {
        q = Math.floor((Math.random() * 10) / 3) * 0.5
    } while (q == qold)

    // Поворот
    context.rotate(Math.PI * q);
    qold = q;

    // Рисование квадрата
    context.fillStyle = "#ff0000";
    context.fillRect(0, 0, rectWidth, rectHeight);
    // Вставка символа
    context.font = "30pt Calibri";
    context.textAlign = "center";
    context.fillStyle = "#0000ff";
    context.fillText("\u2603", 20, 33);
    a++;
    if (a == 50) {
        clearInterval(b)
    };
    // Восстановление
    context.restore();
  }, 1000);
  </script>
</body>
</html>

Zemsky 18.12.2013 20:09

Правильно ли я понял, что надо было применить другой цикл? Сейчас еще раз осмыслю. Спасибо! Продолжаю изучать. :)

рони 18.12.2013 20:40

для вашего варианта сколько раз прежнее значение может повторится за 50 шагов
for (var i = 0, k = 0, q = 0, qold; i < 50; i++) {
      if (q == qold) {
          q = Math.floor((Math.random() * 10) / 3) * 0.5;
      };
      if (q == qold) k++;
      qold = q;
  }
  alert('50 -> ' + k)

Zemsky 18.12.2013 21:13

Спасибо! Можно попробовать организовать алгоритм так, чтобы за N шагов каждое положение из 4-х повторялось N/4 раз. Сейчас я, правда, попытаюсь привязать клавиши Стрелки клавиатуры к повороту квадрата. Почти игра получается. Если правильно ответил как повернут квадрат, очко плюс, если неправильно, минус. Все интереснее...

рони 18.12.2013 21:23

Цитата:

Сообщение от Zemsky
Можно попробовать организовать алгоритм так, чтобы за N шагов каждое положение из 4-х повторялось N/4 раз.

массив 4 элемента -- перемешиваем -- выбираем -- закончился массив - переходим к 1 шагу

nerv_ 18.12.2013 21:36

http://www.w3.org/html/wg/drafts/2dc...nvas/#examples

Zemsky 18.12.2013 21:41

Цитата:

Сообщение от рони (Сообщение 287687)
массив 4 элемента -- перемешиваем -- выбираем -- закончился массив - переходим к 1 шагу

Именно это и смотрел. Но при переходе на следующий массив надо обеспечить, чтобы 1 элемент второго массива не был бы равен последнему из первого.

Zemsky 18.12.2013 21:45

Цитата:

Сообщение от nerv_ (Сообщение 287695)

Да, я этот ресурс знаю. Спасибо!

рони 18.12.2013 22:15

:write:
генератор цепочек неповторяющий подряд и равномерного распределения для любого количества элементов >=3.
<!DOCTYPE HTML>
<html>
<head>
  <title>Untitled</title>
</head>
<body>
<script>
function rund(e) {
    function d(b) {
        for (var a = b.length - 1; 0 < a; a--) {
            var c = Math.floor(Math.random() * (a + 1)),
            d = b[c];
            b[c] = b[a];
            b[a] = d
        }
        return b
    }
    var a = [],
        c = [];
    for (i = 0; i < e;) a[i] = ++i;
    d(a);
    return function () {
        var b = a.shift();
        c.push(b);
        1 == a.length && (d(c), a = a.concat(c), c = []);
        return b
    }
};

 var N = 40000,
     a = [],
     e = 4,
     z = rund(e),
     i;
 for (i = 0; i < e + 1; i++) {
     a[i] = 0;
 }
 for (i = 0; i < N; i++) {
     a[z()]++;
 }
 alert(a); //проверка равномерности ноль неучитывается
 for (i = 0; i < 40; i++) {
     document.write(z()+' '); //для примера
 }
</script>
</body>
</html>

Zemsky 18.12.2013 22:32

рони,
Вы это сходу написали? Да... :) Мне есть куда стремиться.

рони 18.12.2013 22:36

Zemsky,
:victory: :dance: дорогу осилит идущий

Zemsky 18.12.2013 22:54

Ищущий да обрящет..:write:

Со стрелками через case разбираться?

рони 18.12.2013 23:00

Цитата:

Сообщение от Zemsky
Со стрелками через case разбираться?

как удобнее -- можно и через ключи обьекта

рони 18.12.2013 23:06

Zemsky, на всякий случай
http://learn.javascript.ru/keyboard-events

Zemsky 18.12.2013 23:35

рони,
Вот спасибо! Буду разбираться..

рони 19.12.2013 00:03

Zemsky,
вариант управления стрелками ... кликнуть по квадрату вначале
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  div{height:100px;width:100px;background:#006400;position:relative}
  </style>
  <script>
window.onload = function () {
    var b = {
        39: ["left", 5],
        37: ["left", -5],
        40: ["top", 5],
        38: ["top", -5],
        left: 0,
        top: 0
    };
    document.body.onkeydown = function (a) {
        a = a || window.event;
        a = a.keyCode;
        var d = document.getElementById("show");
        if (a in b) {
            var c = b[a][0];
            b[c] += b[a][1];
            d.style[c] = b[c] + "px"
        }
    return false
}
};
</script>
</head>

<body>
<div id="show" ></div>
</body>
</html>

Zemsky 19.12.2013 00:53

рони,
Кладу в архив. Это ассоциативный массив? Вот со второй частью полная непонятка...

рони 19.12.2013 01:10

Цитата:

Сообщение от Zemsky
Вот со второй частью

что есть вторая часть?

Zemsky 19.12.2013 01:16

Цитата:

Сообщение от рони (Сообщение 287747)
что есть вторая часть?

document.body.onkeydown = function (a) {.......

Я еще только начал осваивать. Поэтому и задачу несложную себе формулирую. И постепенно усложняю.

tsigel 19.12.2013 18:28

рони,
Красиво, только зачем так сокращать, всё таки не в разработку отдаёте, а объясняете человеку :) А то получается полу обфусцированный код :)

tsigel 19.12.2013 18:33

Zemsky,
a = a || window.event;
Это для кроссбраузерности. В итоге в а будет событие. (event)

a = a.keyCode;
Перезаписали в а код нажатой клавиши, которую взяли из события

if (a in b) {
проверяем есть ли в объекте b ключ a

var c = b[a][0];
объявляем переменную c равную первому элементу массива в объекте b c ключём a

b[c] += b[a][1];
изменяем left или top в b в зависимости от клавиши

d.style[c] = b[c] + "px"
смещаем квадрат

рони 19.12.2013 18:35

tsigel,
почему
Цитата:

Сообщение от tsigel
полу обфусцированный

там что-то ещё можно сократить? )))
научусь имена давать вразумительные - будет несокращённый вариант.
и спасибо что обьяснили мой код

tsigel 19.12.2013 18:37

рони,
Ну как же! Ещё можно удалить переносы на новую строку и пробелы


Цитата:

Сообщение от рони
и спасибо что обьяснили мой код

Незачто

:)

Zemsky 19.12.2013 19:44

tsigel, рони,

Искренняя благодарность! Сейчас, правда, внучку привезли. Так что ей все внимание. А к изучению вернемся завтра..


Часовой пояс GMT +3, время: 22:31.