Обновить
Комментарии 92

А вы пробовали тестировать при дрожании камеры, изменениях угла, поворотах и прочих нормальных условиях?
Вряд ли ведь у двух людей будут штативы, чтобы закрепить на них телефоны, например.


P.S. За Vecty спасибо, звучит интересно, но верстка выглядит чересчур многословной. Оно, кстати, компилируется в стандартный таргет wasm из go 1.11?

Ну, такой задачи не стояло, и я, конечно, тестировал для идеальных условий, чтобы оценить вообще порядок. Но сам детект QR кода реализован непосредственно в OS (AVFoundation умеет автоматически много чего распознавать – я так полагаю, с помощью нейросетки), и при ручных тестах у меня сложилось впечатление, что легкое дрожание и изменение ракурса вообще не влияет – главное, чтобы код оставался в кадре. Вполне допускаю, что на более старых телефонах это не так хорошо – но iPhone XS всё таки по мощности сравним с Macbook Pro, так что неудивительно.

Насчёт wasm — сам сильно жду, и это в ближайших планах, уже висит PR открытый. Я так понимаю, это будет политическое решение – уход от gopherjs к wasm, поскольку поддержка обоих вариантов там не сильно получается – нужно API менять немного.
QR достаточно надежно сканируются, как живущий на данный момент в Китае говорю, они тут везде. И туда до 30% избыточных данных запихать можно, для уверенности сканирования.
А если снимать в замедленном режиме iPhone и увеличить FPS. Может быть получится добиться лучших результатов?
Ммм, интересный вопрос. Замедленный режим позволяет снимать с высоким FPS, но скорость с которой AVFoundation может распознавать коды на кадрах, по идее, константа и будет определять реальную скорость. При этом, полагаю, slow motion режим как-то особенно реализован и в нём детект лиц и кодов выключен, поэтому придётся записывать, а потом проигрывать на оптимальной скорости – что уже удлиняет и усложняет весь процесс. Но идея интересная.
Проблема с UI на веб-технологиях в том, что HTML и CSS ещё хуже, чем JS. Javascript — обычный динамический язык программирования, не без недостатков, но и со своей красотой. А вот вёрстка… там такое количество исторических артефактов, несовместимостей, всяких вендорных префиксов, логических несоответствий, что JS по сравнению с этим просто образец стройности.
Попробуйте объяснить новичку как отцентрировать что-то; как сделать несколько элементов в одну строку с разным содержимым, но одинаковой высотой и пр. В итоге даже простые вещи на HTML+CSS делать на порядок сложнее, чем на нативных технологиях, а вещи сложные всё равно сможет сделать только человек, вбухавший в это дело кучу лет.
P.S. Если вы знаете ресурсы где такие вещи объясняются, эдакий tutorial/список best practices, то киньте ссылочку, пожалуйста.
Центрировать что-то в веб UI это ужасно, да. Я лично очень жду пришествия Qt на wasm – вот уже есть даже Go-bindings: therecipe.github.io/widgets_playground

Но не могу согласиться, что костыльность HTML/CSS инвалидирует костыльность JS – мне кажется, они как раз очень гармонично смотрятся. Вот даже опыт с Vecty показывает, что с DOM/CSS на порядок проще работать, когда есть возможность легко и просто абстрагировать сложность, рефакторить и внятно описывать компоненты.

Про ресурсы по центрированию в CSS не подскажу, к сожалению, но на ответы подпишусь :D
А в чём заключается костыльность JS? Я не являюсь его фанатом, иногда приходится писать (как и почти всем в наше время), даже освоил Vue.js на базовом уровне и лично я не сталкивался с поведением Javascript, которое бы меня выбешивало. Может быть, потому что я давно пишу на Python, может быть, потому что полистал Дэвида Флэнагана (поэтому с NaN и == проблем не было, а те, которые были — решались простейшей отладкой через console.log), но я должен признаться, что в общем это был позитивный опыт — это мультипарадигменный язык, даёт простор для творчества и если ты хоть немного умеешь эту свободу применять, то это интересно.

А вёрстка… там иногда доходило до такого отчаяния, что хотелось всё бросить. HTML и CSS ведут себя совершенно непредсказуемо и нелогично для непосвящённого в их извращённые рецепты. И отладки никакой нет. Конечно, есть инспектор элементов, но он не слишком полезен.
Ну, я не особо хочу озвучивать свою позицию про JS, чтобы не провоцировать холивары, но язык программирования это слишком важный и сложный инструмент, чтобы лепить его за пару недель и хаотически развивать. Есть такая известная цитата:
We become what we behold. We shape our tools and then our tools shape us

Инструменты, которые мы используем для решения задач, формируют то, как мы их решаем, наши дальнейшие решения, принципы и ценности, и, в итоге, всю экосистему. То, во что превратил наспех созданный язык для скриптиков, индустрию разработки софта – это сильнейший удар по борьбе с добавленной сложностью, с которой боролись пионеры computer science, такие как Дейкстра и Хоар, ещё в 70-е.

Поэтому да, моя главная претензия не столько к самому языку (что можно ждать от быстрой поделки), а к тому, что благодаря историческим недоразумениям это стало единственным языком доступным на внезапно ставшей основной платформе, и сформировало очень поломанную экосистему и целые поколения разработчиков, выращенных на поломанных принципах, сильно далеких от основного мейнстрима мира программирования. Эх, всё равно холиварно получилось.
Я лично очень жду пришествия Qt на wasm

В 5.12 будет, если не перенесут, то в этом месяце. Проверил, вполне юзабельно.

Попробуйте объяснить новичку как отцентрировать что-то; как сделать несколько элементов в одну строку с разным содержимым, но одинаковой высотой и пр. В итоге даже простые вещи на HTML+CSS делать на порядок сложнее, чем на нативных технологиях, а вещи сложные всё равно сможет сделать только человек, вбухавший в это дело кучу лет.
P.S. Если вы знаете ресурсы где такие вещи объясняются, эдакий tutorial/список best practices, то киньте ссылочку, пожалуйста.

Даже две ссылочки:

flexboxfroggy.com/#ru
cssgridgarden.com/#ru
Это действительно красиво и удобно, но…
caniuse.com/#feat=flexbox — 82% пользователей в России имеют поддержку flex
caniuse.com/#feat=css-grid — 76% пользователей в России имеют поддержку grid
Это слишком мало.
Есть ли для вёрстки что-то типа Babel, когда сам ты пишешь на гридах или каком-то псевдоязыке, а потом транспилируешь код в более совместимый со старыми браузерами?
То 82% погоду показывает. У флексов, особенно с префиксами, отличная поддержка, если отсечь IE (Edge можно не отсекать) и совсем древние Safari <7. Их можно использовать сейчас буквально для всего.
Гриды — да, надо с осторожностью пока. Тут зависит от конкретного сайта и его аудитории.
Вы либо застряли в нулевых и верстаете под ie6, либо просто не в курсе современных стандартов HTML и CSS. В частности, центрировать блоки можно в три строчки с помощью flex-layout. Колонки с одинаковой строкой – в две строчки с помощью того же flex'а.
Какое облегчение, всего-лишь 3 строчки что бы выставить элемент по центру, торжество технологий прям...
Хм, а если у тебя родительский див не имеет заданной высоты, в него вложено два дива, в одном текст выводится в одну или две строчки, во втором — в одну. Надо чтоб второй див был прибит по высоте к низу первого?
Нет ничего проще. jsfiddle.net/43huk69s/2

<div class="parent">
  <div class="child">В этом блоке<br>Две строки текста</div>
  <div class="child">А в этом одна</div>
</div>

<style>
.parent {
  border: 2px solid orange;
  padding: 5px;
  display: flex; /* Тут важна только эта одна строчка */
}
.child {
  border: 2px solid lightgreen;
  margin: 5px;
  padding: 5px;
}
</style>


Если я правильно понял и речь шла об одинаковой высоте обоих блоков. А если нужно было не менять высоту второго блока, а просто сделать, чтобы он внизу располагался, то к родителю надо ещё добавить align-items: flex-end;
Спасибо, это как-бы работает, но есть нюансы…
У нас тут своя атмосфера:
IE в режиме совместимости это игнорит, что лечится. А вот через конвертер html-pdf (wkhtmltopdf, даже последний) — не работает…

А если поставить два зеркала, получится сделать клиент-сервер. :)

Хаха, но нет. QR коды не читаются в отражении (точнее, некоторый софт для декодера умеет распознавать отражённые QR-коды и исправлять перед считыванием, но вообще нет). Ну и протокол не готов к двустороннему общению. Но идея забавная.
Зачем зеркала, просто экранами друг к другу и использовать фронтальные камеры.
Фронтальные камеры хороши только на топовых моделях.
А вот для, например, контроля передачи, синхронизации скорости и повторного запроса нераспознанных кадров — можно использовать камеру на сервере и вспышку на клиенте.
Круто! Тоже когда-то хотел подобное сделать, но руки не дошли. Пару моментов:

1. Для связи телефон-телефон хорошо бы обратную связь прикрутить, тогда передача больших файлов станет более-менее реальной. Теоретически принимающий телефон может квитировать приём данных сигналя вспышкой передающему на фронтальную камеру. Вспышки и фронтальные камеры сейчас есть практически у всех.

2. Согласен, что QR код слишком избыточен. Надо свой формат метки придумать без корректирующих кодов. Контроля каждого фрейма с помощью какого-нибудь CRC будет вполне достаточно.
ЕЩЕ ЧУТЬ чуть и так же сделаем передачу по аудио каналу и будем переизобретать протокол V.92 :-)
ИК-порт переизобрели вот, правда во много раз медленнее, и ресурсоемкость намного выше… Все чаще возникает ощущение «цикличности моды», это когда молодежь начинает одеваться как твоя бабушка в молодости, но с таким лицом, как будто они открыли Америку.
Так уже. «Audio MODEM» в маркете. И небольшая кучка видео на YouTube ищется.
Правда, не уверен, что из этого с обратной связью работает.

Аудио канал, кстати, выглядит несколько более осмысленным и полезным для мелких объемов данных. Для примера можно посмотреть как некие Chirp и Shuttl оплату проезда маршрутками в Индии сделали.
1. Для связи телефон-телефон хорошо бы обратную связь прикрутить, тогда передача больших файлов станет более-менее реальной. Теоретически принимающий телефон может квитировать приём данных сигналя вспышкой передающему на фронтальную камеру. Вспышки и фронтальные камеры сейчас есть практически у всех.
Хм, вайфай и тотал коммандер с помощью QR позволяет переносить данные между компом с Windows (надо расширение найти на сайте) и телефонами на Windows Phone, Android и вроде даже Apple.

Это, чёрт возьми, восхитительно! Просто слов нет, я серьёзно.

Вай зачем такой сложный QR-код, если можно передавать мерцанием, где белый фон единица, а черный — ноль?
А можно и звуком разной частоты для единицы и нуля… ой кажется я переизобрел формат записи программ для спектрума. R tape loading error :))
Вай зачем такой сложный QR-код, если можно передавать мерцанием, где белый фон единица, а черный — ноль?
При 60 fps скорость передачи будет 7,5 байт в секунду.
и это без определения ошибок и уж тем более коррекции
Если протокол будет двусторонним, то можно и оплату чего-нибудь прикрутить. А если еще цветом кодировать?
Прикольная технология. Не соображу, где бы мог её применить, но как идея интересно.

p.s. почему то придумался способ «шпиёнский» канал передачи данных через систему двух смартфонов, двух зеркал и двух телескопов. Вряд ли реализуемый в реальности, но для кино про хакеров вполне.
Двигаем дальше — передаем анимированные изображения с помощью анимированных изображений, видео и звук с помощью QR видео и т.д.
О, так можно же в QR-gif зашифровать QR-gif с шифрованным QR-gif!
Как нам повезло что берестяные грамоты этого не могли. А то написал кто то так одну шифрованную книгу — до сих пор пытаются прочесть.
НЛО прилетело и опубликовало эту надпись здесь

Так он же просто на ацтекском написан.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Классно получилось. Не смотрели по какому принципу реализовано в apple watch pairing? там такой вращающийся qr-подобный шарик который надо телефоном сканировать. Вопрос именно в том, что он вращается и как это парсится

Там крутая технология, я пробежался по обоим патентам – если вкратце, то картинку они могут какую угодно рендерить (не обязательно этот шарик с частицами). Они анализируют усреднённое изменение в luminance (светимости), и передают данные именно через этот параметр, а вот chrominance (цветовая составляющая) там всё равно какая. Гениальность в том, что человеческий глаз гораздо более чувствителен к изменениям в цветовой составляющей, чем в светимости, и не видит тех изменений, но софт очень надёжно может из изменений светимости вытащить данные.

офигеть. а скорость такой передачи известна?
Я не нашёл, но полагаю что маленькая – не под скорость, всё же, оптимизировали )
Классная реализация. Можно использовать как аналог NFC для обмена контактами, либо спаривания телефонов через bluetooth, wi-fi для передачи большого объёма информации.

А почему необходимо использовать GIF, почему нельзя новые кадры на ходу генерировать?

В принципе можно, просто GIF удобней был тем, что можно гарантировать FPS – там задержка между кадрами прямо в файл записывается. При генерации каждого кадра, по идее, достаточная порция времени будет уходить на генерацию картинку, и высчитать, сколько реально осталось ждать до следующего кадра будет не сильно тривиально. Хотя стоит попробовать, конечно, всё равно.

Как раз таки узнать сколько времени ушло на генерацию и соответственно, сколько осталось, довольно не сложно ( как мне кажется). А почему нельзя использовать два потока — один для генерации и второй — рендера?
Если я правильно понимаю, у принимающей стороны кадры должны быть синхронизованы с передающей?

Узнать может и не сложно, но что делать, если генерация заняла больше времени, чем задержка между кадрами? (а там почти всегда так). А горутины всё равно в скомпилированному JS будут в одном потоке работать.


принимающей стороны кадры должны быть синхронизованы с передающей?

Как раз нет — рассинхронизация частот будет влиять только на общее время передачи, но всё равно будет работать. Я там в описании идеи протокола немного объяснял этот момент — фреймы можно вообще в любом порядке принимать.

Ну если по потокам не развести никак — то грустно конечно.
Хотя если принимающая сторона не завязана на длину кадра, то в чем великая проблема, если новый кадр отрисуется чуть-чуть позже?
Так вроде есть асинхронный js. Получается GopherJS просто не умеет асинхронный го в асинхронный js?
Асинхронный JS тоже только одно ядро умеет )
Хм… 1кб в секунду это очень много для недетектируемой передачи данных. Способов использования в голове сразу много появилось…
Столкнулся недавно с похожей проблемой. Ограничение на размер данных обошел просто закодировав ссылку на gist с base64 data.
Круто, хотя и сложно найти реальное применение.

Не думали о реализации асинхронной двухсторонней связи для подтверждения приёма очередного пакета? Вспышкой там моргать или через звук данные передавать.

То есть, передатчик показывает кадр с qr-кодом, убеждается, что приёмник его прочитал, а потом показывает следующий. С помощью обратной связи можно даже регулировать количество данных в кадре, ведь если камера хорошая, а процессор быстрый, можно и по 1276 байт данные передавать. К тому же приёмник не будет вынужден ждать весь цикл, когда один кадр пропущен.
Ну, настолько я усложнять не хочу — почти любое решение тут сильно ограничивает круг применения. Я вот только сегодня понял, что такую анимированную гифку даже Apple-овские Shortcuts скриптинг может сделать – можно сказать «Сири, сгенерируй-ка мне QR из последнего скриншота», и скрипт возьмёт скриншот, разобъет на куски (вот тут еще не уверен, умеет ли такое), сгенерирует QR на каждый и склеит в GIF-ку (такое точно умеет). В общем, less is more.

Да и дорого слишком реализовывать протокол с подтверждениями – Шэннон не одобряет :) Я буду чуть позже фонтанные коды реализовывать, чтобы проблему с ожиданием цикла решить.
Если добавить цвет, можно увеличить пропускную способность во много раз. Но чем больше цветов, тем сильнее придется переживать еще и о цветопередаче.
Придумал вот такой способ image
можно сложить много qr кодов разных цветов)…

Цветопередача у разных мониторов ± одинаковая, конечно, но качество работы камер при разных освещениях и разная цветовая температура ламп могут здорово попортить практичность.

Java, Python или JavaScript, что, к сожалению, делало код практически непортируемым

это какая-то шутка?

Нет, не шутка.


Я действительно не знаю способов использовать код на Java, Python или JS на ноутбуке, в вебе и в iOS и Android проекте. Возможно, нужно было добавить, что "непортируемым, в сравнении с Go", потому что в Go это всё однострочные команды и меньше секунды ожидания:


Windows PE
GOOS=windows go build


Linux ELF
GOOS=linux go build


MacOS X Mach64
GOOS=darwin go build


iOS Framework
gomobile bind -target=ios .


Android AAR Native Code
gomobile bind -target=android .


Web (JS)
gopherjs build


И это всё фактически из коробки (gomobile и gopherjs ставятся отдельно также однострочниками).

т-с-с-с, разговор не об этом… =) не начинайте
Java была одной из самых первых кто был портируем под различные платформы. Это один из самых портируемых языков.
Python собирается и запускается практически на любой *nix, там же виндовс и даже на андроиде работает (см. Kivy)
JS с приходом NodeJS работает едва ли не на любом чайнике.
Так что с портированием у них все хорошо. А вот удобство сборки кода под платформы — это уже другой вопрос и к кроссплатформенности отношения не имеет.
Я не употреблял слово «кроссплатформенность».
Была конкретная задача использовать код на трёх платформах и ни один из вышеприведённых языков не позволял сделать это достаточно просто.
Тогда что по вашему портируемость как не перенос кода с одной платформы на другую?

Гениально! Как увидел сразу первая мысль "Это же белый шум из телевизора!" он же вроде как реликтовое излучение. Может это и есть разгадка тайны молчания космоса? Другие цивилизации просто передают данные посредством QR кодов высокой плотности! :)

Можно попробовать и через вибрацию — ловить акселерометрами.
Tx — это не трансфер, а передача (transmission). Трансфер — это XFR.
Прочитал статью и осталось негативное впечатление — чувствуется писатель юн и горяч и допускает ошибки молодости проявляя категоричность:
— если вы не знаете инструмент — не стоит негативно о нем отзываться
— сложность в фреймворках величина постоянная и никуда не девается, а лишь перемещается из одного места в другое — порой фреймворк на котором легко написать Hello world не способен обеспечить создание enterprise приложения
С горячим соглашусь )

Инструмент инструменту рознь. Мнение о том, что все инструменты одинаково хорошо, «просто нужно их получше узнать» мне чуждо, и, честно говоря, считаю его крайне вредным. Все программисты должны понимать, что выбор инструментов очень сильно будет влиять на их работу, продуктивность и даже дальнейшую судьбу. Но умение отличать плохие инструменты от хороших приходит с опытом, конечно.

Про постоянную величину сложности фреймворков – это вот сильно мимо. Интересно было бы послушать, как вы пришли к такому выводу.
Спасибо, круто всё описано, как всегда у Вас.
Некоторые вопросы вызывает vecty. Давно смотрю на неё, но пока опасаюсь использовать в боевом коде. Там написано, что проект всё ещё в стадии эксперимента и есть важные не решённые проблемы. С другой стороны его контрибьютит в том числе мэйнтейнер gopherjs, что означает, что проект вряд ли будет депрекейтнут. Как Вы полагаете, будет ли vecty + gopherjs + go полноценной заменой react + webpack + typescript. Естественно речь о проектах без лигаси и большого количества внешних js библиотек
Спасибо. Да, безусловно, это пока эксперимент, и для более-менее серьезных продакшн проектов ещё сыроват. Там есть свои проблемы (связанные, опять таки, с фактом того, что в итоге всё равно JS на выходе) – например при частом обновлении виджета из горутины (прогрессбар быстрый, допустим), может понадобится вручную вызывать `runtime.Gosched()` иначе виджет не будет обновляться.
Так что на данном моменте как полноценную замену существующих стеков для фронтенда не могу рекомендовать.
Спасибо. Да, чуть выше обсуждали уже альтернативные коды. У QR кодов всё-таки главный плюс это встроенная поддержка в мобильных SDK и вообще везде. Я могу такой анимированный QR сгенерировать даже через Apple Shortcut скриптинг :) Less is more.
А нельзя использовать вспышку принимающего аппарата и фронтальную камеру передающего для синхронизации?
Первой мыслью было использовать Bluetooth, но это не так удобно, как кажется – относительно долгий и не всегда работающий процесс обнаружения и спаривания устройств слишком затрудняет задачу.

Спасибо за статья и реализацию, но интересно почему изначально wi-fi не рассматривали? Сейчас же существует много приложений для передачи файлов через Wi-Fi Direct, да и из коробки часто поддерживается
Спасибо, вот что-то подобное Wi-Fi Direct я очень давно хочу, чтобы было из коробки и стандартно для всех девайсов, но пока это далеко от истины. iOS-устройства, например Wi-Fi Direct не поддерживают, у них там своя технология.
Нашел приложение ShareIt от Lenovo, есть под все основные платформы, iOS в том числе, заявлена передача файлов между разными платформами по Wi-Fi, нет только возможности проверить.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.