Краткое отступление. Извините за паузу в записях Design Diary (дневник дизайна). В последнем порыве, чтобы отправить Pedometer ++ v5, у меня не хватило времени, чтобы поддерживать их. Не бойтесь, хотя я записал кучу тематических идей, чтобы написать о них теперь, когда они были отправлены, и на меня снова меньше давят.
В рамках предстоящей функции Widgetsmith я хотел рисовать линейные градиенты. Я делал это бесчисленное количество раз, используя замечательный стиль заливки LinearGradient. Это прекрасно работает и может легко встраиваться в множество различных форм и ситуаций в SwiftUI.
Однако всякий раз, когда я использовал их раньше, я использовал только встроенные значения direction (направления):.top,.topTrailing,.leading и т. д. И, если быть честным, это были единственные варианты, которыми я располагаю.
Для этой конкретной функции я действительно хотел иметь возможность рисовать градиенты под произвольными углами, а не только по горизонтали, вертикали и наклону. Я начал немного копаться и, к своему удовольствию, обнаружил, что на самом деле это уже встроено в LinearGradient.
LinearGradient принимает в качестве управления direction аргумент типа UnitPoint. Обычно вы взаимодействуете с ними, используя встроенные параметры, но оказывается, что это просто нормализованная пара X/Y под капотом. Так что, если бы я мог подобрать подходящее значение X/Y, я мог бы рисовать свои градиенты под любым углом.
Теперь вся хитрость заключалась в том, чтобы выяснить, как рассчитать эти пары. Я начал пытаться сделать это с помощью математики (=)) и быстро разочаровался. Я уверен, что для этого есть умное алгебраическое решение, но я не смог найти его после небольшого поиска.
Затем я понял, что на самом деле я мог бы просто упростить всё это, поскольку меня заботила только одна переменная за один проход (например, значение Y на левом краю и значение X на нижнем краю).
Так что я просто взял каждое ребро по очереди и вычислил относительную долю ребра, которую он покрыл бы под заданным углом. Я просто делаю это с помощью базового расчета линейной пропорции.
Это прекрасно работает и позволяет рисовать градиенты под любым углом. Если вы хотите увидеть код или использовать его самостоятельно.
Вот он на GitHub.
Уточнение:
Rob Mayoff и robb указали мне, что мой метод не совсем правильный. Поскольку я выполняю линейную интерполяцию, а не тригонометрическую, мои повороты немного отличаются от фактического угла. В этом случае разница крошечная и визуально очень трудно различить, но всё же это не совсем правильно.
Вот анимация, сделанная Робом для иллюстрации этой ошибки:
Rob и robb были достаточно любезны, чтобы опубликовать свои альтернативные решения, которые правильно подходят для этого.