Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как сделать required для одного из трех select?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Перед тем, как «дальше» проверяйте, выбрано ли значение хотя бы в одном из трёх <select>
    Ответ написан
  • Как отрисовать контур в SVG?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Небольшая проблема была в том, что у вас этот контур состоял из двух кусков: правого верхнего уголка и всего остального (привет дизайнеру?). Исправил путь так, что теперь это один сплошной путь, без лишних точек и без ненужных групп <g>.
    скриншот
    bde82874e0b0474da2c847039e028361.png

    Делаем две копии этого пути, одна под другой. Нижняя – частым синим штрихом. Верхняя – чуть более широким штрихом и цвета фона.

    Подобрал на глаз длину штриха 2200, чтобы полностью закрывал всю длину, и на эту же величину смещаю паттерн при наведении мышки. CSS transition делает анимацию плавного перехода от нулевого смещения (паттерн начинается с 0 и полностью закрывает нижнюю копию) до смещения в 2200, чтобы начался пробел и полностью открыл нижний путь.

    Чтобы срабатывали стили :hover при наведении мышки пришлось обернуть SVG в <div>

    Fiddle
    Ответ написан
    1 комментарий
  • Как написать алгоритм поиска соседних элементов?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Идея с отдельной работой по X и по Y неплохо работает. На каждом кадре проверяем каждую из 200 точек (это совсем не много).

    Сортируем массив точек по их X-координате. Двигаемся слева направо, выбирая очередную точку.

    Смотрим от неё влево (чтобы не проверять одну связь дважды, выбираем полуплоскость от точки) и отбираем только те точки, чей X отличается не более, чем на radius.

    Из них смотрим только на те, у которых Y не более, чем на radius отличается (уже в любую сторону: и вверх и вниз).

    У них проверяем уже евклидово расстояние – корень из суммы квадратов расстояний по X и по Y – чтобы было не больше radius. У таких есть «связь» – рисуем им ребро.

    Работающий fiddle (неминифицированный исходник на github)
    538264abb31847baa28fe05e015ac13c.png

    На компе даёт около 60 fps, на мобильнике от 40 до 55, т.е. совершенно приемлемая скорость при 200 точках.

    Первая версия ответа

    Интересна ситуация, наихудшая для оптимизации: когда за 1 кадр может поменяться максимальное число связей. Предположу, что это сетка из равносторонних треугольников, где длина ребра равна «триггерной» дистанции:
    картинка треугольной сетки
    5297fe1c584f4551aca5b77a2a987549.jpg
    Тут большинство точек, кроме крайних, взаимосвязаны. У каждой по 6 ближайших соседей. Примерно 200 * 6 / 2 = 600 связей (чуть меньше из-за краёв).

    Если такую сетку пропорционально увеличить на любую малую величину, сразу все связи порвутся, их станет ноль. Пусть на месте останется, скажем, левый верхний угол сетки. Тогда наибольший путь проделает нижний правый угол. Тут вопросы к особенностям вашей задачи:
    1. округляются ли координаты до целых или до какой-то точности?
    2. какой наибольший путь может проделать за один кадр точка?

    В идеальном мире всем достаточно проделать бесконечно малый шаг, и, вуаля!, было 600 связей, стало 0. Такой же шажок назад – не было связей, и вот их 600. Т.е. надо бы в каждый кадр проверять 600 ребер. Считать это за теоретический предел оптимизации?

    Сущности
    Точки и рёбра. Ребро ссылается на две точки. Точка ссылается на рёбра. Ребро имеет длину и, в зависимости от длины, может быть «видимым».

    Важнее всего следить за рёбрами, длина которых близка к пороговой – и с меньшей и с большей стороны. Такие стоит проверять почти каждый кадр, т.к. статус ребра может поменяться за один кадр. Прочие рёбра и кандидаты в рёбра проверять можно изредка.

    Можно давать рёбрам веса, пропорциональные желаемой частоте их обновления. Скажем, от 0 до 1. Вес равный 1 значит, что нужно проверять каждый кадр. Например, вес W = Math.max(0, D - Math.abs( length - D))/D, где D – пороговая дистанция.

    Остаётся сделать механизм, отбирающий рёбра в работу на очередном кадре, исходя из их весов. Запоминать время, когда ребро было обновлено. Приоритет его попадания в обработку равен W * (time - timeUpdated)
    Ответ написан
    3 комментария
  • Как оптимизировать svg-файл, в котором находится 5 000 точек, для встраивания на страницу?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Браузеру тяжеловато отрисовываеть такое количество элементов.

    Canvas вместо SVG не рассматривали?
    Ответ написан
    1 комментарий
  • Как отрисовать SVG при наведении?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Отрисовку делают изменяя смещение очень длинного штриха stroke-dashoffset, так, чтобы штрих появлялся, создавая эффект прорисовки.

    В вашем случае, можно делать наоборот - исчезновение сплошной линии цвета фона, скрывающей под собой такую же, но частым пунктиром.

    Недавно отвечал на близкий вопрос и сделал демо.
    Ответ написан
    3 комментария
  • Как вычислить пересекаются ли много многоугольников?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вкратце:
    1. набросать фигуры по сетке. Пусть они где-то накладываются, где-то выходят за границу полотна.
    2. дать им «расслабиться» – будто они льдины, свободно плавающие. И при этом взаимно-отталкиваются. Для упрощения можно посчитать, что каждая точка отталкивается от всех точек других фигур, сила пропорциональна квадрату расстояния. Просчитать несколько «шагов» такого плавания.

    Для определения, пересеклись ли полигоны, как уже написал Хасан Истамкулов, надо проверять пересечение отрезков. Если у двух фигур найдётся, что какие-то два отрезка пересеклись, значит есть коллизия:
    8186a53eefde4e0dbbba93ce279bf961.png
    Ответ написан
    Комментировать
  • JS: getImageData / putImageData как скопировать изображение?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    у putImageData() две сигнатуры: 3 аргумента или 7 аргументов:
    ctx.putImageData(imagedata, dx, dy);
    ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);


    выдрать из него кусочек.. например [0, 0, 10, 10]

    var pixels = context.getImageData(0, 0, 320, 240);
    var data = pixels.data; // в data попадает одномерный массив.
    target.putImageData( pixels, 15, 15, 0, 0, 10, 10);
    /*
    15, 15 – где разместить (отступив по 15px слева сверху в target'е)
    0, 0 – откуда копировать в координатах context'а
    10, 10 – ширина, высота региона копирования
    */
    Ответ написан
    3 комментария
  • Почему не срабатывает onload() на vk.com?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так работает:
    var mdk_win = window.open('https://vk.com/mudakoff', 'mdk_win', 'width=600,height=400');
    mdk_win.addEventListener('load', function(){
      console.log('окно MDK загружено');
    });
    Ответ написан
    2 комментария
  • Как сравнить два массива и удалить из второго совпадающие элементы JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    arr2 = arr2.filter(e => !~arr.indexOf(e));
    // facebook.com,ya.ru


    Метод массива filter() создаёт новый массив, в котором остаются только те элементы исходного, для которых функция проверки вернула true.

    Внутри этой функции проверяем, есть ли очередной элемент в массиве arr: вернёт ли indexOf() что-то отличное от -1. Для короткой записи такой проверки удобно использовать побитовое НЕ ~ которое даст 0 в единственном случае, когда операнд равен -1. Его отрицание ! даст true в том же единственном случае. Итого эта функция вернёт true только, если элемент не найден в массиве arr.
    Ответ написан
    2 комментария
  • Как проверить существует ли переменная?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так, как вы написали, ваш код имеет смысл в двух случаях:

    1. Внутри функции:
    function test(varbl) {
      varbl = varbl || 0;
      alert(varbl);
    }
    
    test();
    test( 100500);


    2. Вне функции, и вы должны были бы где-то выше:
    1. объявить эту переменную: var varbl;
    2. дать или не дать ей какое-то значение: if( Math.random() > 0.5) varbl = 100500;

    Тогда далее ваш код вполне будет работать, без ошибок и именно так, как вы и написали.
    Ответ написан
    Комментировать
  • Что делает функция JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Логическое И && принимает значение true в единственном случае – если оба операнда true.

    a && b проверяет по очереди: сначала, приводится ли к значению true первый операнд, a? Если нет, то дальше проверять нет смысла и выражение возвращает первый операнд, а.

    Если же a не пустой и при переводе в логическое true | false даёт таки true, то так же проверяется второе выражение, b.

    В вашем примере сначала проверяется, что там в jj. Если пустота, то более ничего не делается. Если же там, например, функция, то надо проверить и второй операнд. Для этого надо выполнить функцию jj(false).

    Таким образом, проверяется, не пусто ли jj, и если не пусто, то вызывается функция jj(false).
    Ответ написан
    Комментировать
  • Как можно переписать это код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вместо return +a[attr] > +b[attr] ? 1: -1;
    можно return +a[attr] - b[attr];

    const sortFunc = function sortFunc(data, elem) {
    	switch( elem.getAttribute('name')) {
    		case 'id':
    		case 'salary':
    			data.sort((a, b) => +a[attr] - b[attr]);
    			break;
    		case 'user':
    		case 'position':
    		case 'gender':
    			data.sort((a, b) => a[attr] > b[attr] ? 1 : (a[attr] < b[attr] ? -1 : 0));
    			break;
    		default:
    			throw('Bad attribute');
    	}
    };
    Ответ написан
    Комментировать
  • В чем ошибка использования arguments функции?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Calc = function(){
      this.sum = function(){
        return Array
          .prototype
          .slice
          .call(arguments)
          .reduce(function(p,c){return +p+c}, 0)
      }
    }
    
    let c = new Calc;
    c.sum(2,4,6) // 12
    Ответ написан
    9 комментариев
  • Как повернуть многомерный массив на 45 градусов?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Для проверки диагоналей не нужно поворачивать матрицу на 45°, достаточно проверять сумму индексов:
    00 01 02
    10 11 12
    20 21 22

    Диагонали слева снизу вправо вверх:
    00        :  0+0 = 0
    10, 01    :  1+0 = 0+1 = 1
    20, 11, 02:  2+0 = 1+1 = 0+2 = 2

    И так далее. Сумма индексов в таких диагоналях постоянна. Максимум в правой нижней клетке составляет удвоенный макс. индекс.

    Чтобы проверить диагонали слева сверху вправо вниз, надо инвертировать индексы одного из измерений, напр. строк: не 0..N, а N..0
    var arr = [
      'o,x,x'.split(','),
      'x,o,o'.split(','),
      'o,x,o'.split(','),
    ];
    
    var r, c, key, diags = {};
    for(r = 0; r < arr.length; r++) {
      for(c = 0; c < arr[r].length; c++) {
        key = r + arr[r].length - 1 - c; // слева сверху вправо вниз
        // key = r + c; // слева снизу вправо вверх
        
        if( diags.hasOwnProperty(key)) {
          if( diags[key] !== arr[r][c]) diags[key] = false;
        } else {
          diags[key] = arr[r][c];
        }
      }
    }
    
    for( key in diags) if( diags[key] === false) delete diags[key];
    // {"0":"x","2":"o","3":"x","4":"o"}
    Ответ написан
  • Как сделать возврат значения из callback?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Функция user_params() отработает сразу и вернет null. А ответ от ВК будет получен когда-то потом и попадёт во вложенную функцию.

    Как вариант, передавайте третьим параметром функцию, которую позже вызовут и в которую передадут ответ ВК:
    function user_params(id, param, callback) {
      vk('users.get', {user_ids: id, fields: param}, function(error, response){
        if (error) {
          console.log(error);
        } else callback(response[0][param]);
      });
    };
    Ответ написан
    1 комментарий
  • Какой плагин использовать для реализации анимации?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вроде бы можно сделать целиком на CSS3.

    Понадобится картинка, которая при повторении даст такой узор – фигура в центре + 4 фрагмента по углам. Анимировать масштаб этого фона и расширяющуюся маску clip-path, которая сначала показывает только одну центральную фигуру, а затем расширяется и открывает весь экран. Ну и в прозрачность увести фон слегка.
    Ответ написан
  • Стоит ли изучить backbone js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Чтобы никто не сломал себе ногу, стоит разобраться с модулями в JavaScript – начните использовать сборщик: Require.js или Webpack или Browserify. А код разделяйте в небольшие логически изолированные куски - модули – лежащие каждый в своём файле.

    Backbone.js в 2017 по-моему вполне актуален. Он не конкурирует с тем же React, который играет роль View в паттерне MVC. Посмотрите, например, реализацию простейшего TodoMVC на Backbone + React.
    Ответ написан
    Комментировать
  • Как округлить минуты в нужную сторону?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Получить минуты, округлить в большую сторону до 15-минутного значения, установить это значение минут:
    function roundTS(ts) {
      var D = new Date(ts);
      var m = 15 + Math.ceil( D.getMinutes() / 15);
      D.setMinutes(m);
      return D.getTime();
    }


    А если требуется именно с массивом минут, то примерно так:
    function roundMinArr( D, arr) {
      var i, m = D.getMinutes();  
      arr.sort((a,b)=>a-b);
      for(i in arr) {
        if( arr[i] < m) continue;
        D.setMinutes(arr[i]);
        return D;
      }
      D.setMinutes(60 + arr[0]);
      return D;
    }
    
    var D = roundMinArr( new Date('2017-08-16T12:17+03:00'), [0,15,35,44,59]);
    D.toString() // Wed Aug 16 2017 12:35:00 GMT+0300 (MSK)
    Ответ написан
    Комментировать
  • Как сделать при нечётном клике один звук, а при чётном другой?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно, как и просит ТС, прямо в HTML. При первом клике инициализировать массив из двух аудио, и переназначить функцию onclick:

    this.a=[
      new Audio('https://wav-library.net/sfx/mix/LightSwitch.mp3'),
      new Audio('https://wav-library.net/prmusic/rock/Run.mp3')
    ];
    this.f=()=>{ // это будет новый обработчик клика
      var cc=!!this.cc; // для краткости записи
      this.a[+!cc].pause(), // если предыдущий длинный играет - стоп его!
      this.a[+!cc].currentTime=0, // ..и перемотать на начало.
      a[+cc].play(), // играть новый
      this.cc=!cc // переназначить счётчик ( true | false )
    };
    this.onclick=this.f, // переназначить хэндлер клика
    this.f() // вызвать для первого клика принудительно

    CodePen

    HTML с этим скриптом будет такой:
    <td onclick="this.a=[ new Audio('https://wav-library.net/sfx/mix/LightSwitch.mp3'), new Audio('https://wav-library.net/prmusic/rock/Run.mp3')];
    this.f=()=>{var cc=!!this.cc;this.a[+!cc].pause(),this.a[+!cc].currentTime=0,a[+cc].play(),this.cc=!cc};
    this.onclick=this.f,this.f()">click me!</td>
    Ответ написан
  • Как достать нужное свойство из многомерного объекта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    function getById( obj, id) {
      var i, found;
      if( obj.id === id) return obj;
      if( obj.hasOwnProperty('childGroups')) {
        for( i in obj.childGroups) {
          if( found = getById( obj.childGroups[i], id)) return found;
        }
      }
      return;
    }
    
    getById( obj,3) // {"id":3,"parentId":1,"childGroups":[{"id":6,"parentId":3},{"id":7,"parentId":3}]}
    Ответ написан
    Комментировать