Этот ответ может быть немного запоздалым, но вы также можете использовать холст для масштабирования исходного изображения.
function handleDragStart(e) {
var dragIcon = document.createElement('img');
dragIcon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC';
var width = 100;
var height = width * (3/4); // The height must be set explicitly. I'm assuming the image is 4:3 for this example
var c = document.createElement("canvas");
c.width = width;
c.height = height;
var ctx = c.getContext('2d');
ctx.drawImage(dragIcon,0,0,width,height);
dragIcon.src = c.toDataURL();
e.dataTransfer.setDragImage(dragIcon, -10, -10);
}
http://jsfiddle.net/cnAhv/138/
Единственным недостатком этого является то, что холст может быть испорчен, если изображение не происходит от одного и того же происхождения. Подробнее о tainted холсты здесь
def doit(str)
r = /\A#{"(#\\d)\\s*"*str.count('#')}\z/
str.match(r)&.captures
end
doit "#1#2 #3 " #=> ["#1", "#2", "#3"]
doit " #1#2 #3 " #=> nil
Обратите внимание, что регулярные выражения зависят только от количества экземпляров символа '#'
в строке. Поскольку в обоих примерах это число равно трем, соответствующие регулярные выражения равны, а именно:
/\A(#\d)\s*(#\d)\s*(#\d)\s*\z/
Это регулярное выражение было построено следующим образом.
str = "#1#2 #3 "
n = str.count('#')
#=> 3
s = "(#\\d)\\s*"*n
#=> "(#\\d)\\s*(#\\d)\\s*(#\\d)\\s*"
/\A#{s}\z/
#=> /\A(#\d)\s*(#\d)\s*(#\d)\s*\z/
Регулярное выражение гласит: «соответствует началу строки, за которым следуют три идентичные группы захвата, за каждой из которых необязательно следуют пробелы, за которыми следует конец строки. Поэтому регулярное выражение проверяет правильность строки» и извлекает нужные совпадения из групп захвата.
Оператор безопасной навигации , &
необходим в случае отсутствия совпадения (match
возвращает nil
).
Комментарий ОП относится к обобщению вопроса, в котором символ фунта ('#'
) является необязательным. Это можно решить, изменив регулярное выражение следующим образом.
def doit(str)
r = /\A#{"(?:#?(\\d)(?=#|\\s+|\\z)\\s*)"*str.count('0123456789')}\z/
str.match(r)&.captures
end
doit "1 2 #3 " #=> ["1", "2", "3"]
doit "1 2 #3 " #=> ["1", "2", "3"]
doit "1#2" #=> ["1", "2"]
doit " #1 2 #3 " #=> nil
doit "#1 2# 3 " #=> nil
doit " #1 23 #3 " #=> nil
Для строк, содержащих три цифры, регулярное выражение имеет вид:
/\A(?:#?(\d)(?=#|\s+|\z)\s*)(?:#?(\d)(?=#|\s+|\z)\s*)(?:#?(\d)(?=#|\s+|\z)\s*)\z/
[1120]
Хотя это верно что это регулярное выражение потенциально может быть довольно длинным, это не обязательно означает, что оно будет относительно неэффективным, так как предугадывание довольно локализовано.
Да, вы можете использовать
s.scan(/(?:\G(?!\A)|\A(?=(?:#\d\s*)*\z))\s*\K#\d/)
См. Демонстрацию regex
Подробности
\G(?!\A)
- конец предыдущего успешного совпадения |
- или \A(?=(?:#\d\s*)*\z)
- начало строки ([116 ]), за которым следуют 0 или более повторений #
+ цифра + 0+ пробелов и затем следует конец строки \s*
- 0+ пробелов \K
- оператор сброса совпадений, отбрасывающий сопоставленный текст #\d
- символ #
, а затем цифра Короче: начало первой позиции строки соответствует, но только если строка справа (то есть вся строка) соответствует желаемому шаблону. Так как эта проверка выполняется с предварительным просмотром, индекс регулярного выражения остается там, где он был, и затем сопоставление происходит все время ТОЛЬКО после действительного совпадения благодаря оператору \G
(он соответствует началу строки или концу предыдущего совпадения, поэтому (?!\A)
используется для вычитания позиции начальной строки).
rx = /(?:\G(?!\A)|\A(?=(?:#\d\s*)*\z))\s*\K#\d/
p "#1 #2".scan(rx)
# => ["#1", "#2"]
p "#1 NO #2".scan(rx)
# => []