Эллиптический радиальный градиент в CGContext?
Насколько я могу сказать, вы можете использовать два метода для рисования градиентов в CGContext
, это drawLinearGradient
а также drawRadialGradient
, То, что я ищу, это способ определения эллиптического градиента, где я могу определить x
а также y
радиусы.
Пример этой возможности в другой среде (SVG
).
<RadialGradient id="gradient" cx="50" cy="50" rx="20" ry="40" fx="150" fy="75">
Существующая декларация для drawRadialGradient
как следует.
func drawRadialGradient(_ gradient: CGGradient,
startCenter: CGPoint,
startRadius: CGFloat,
endCenter: CGPoint,
endRadius: CGFloat,
options: CGGradientDrawingOptions)
И начальный, и конечный радиусы являются скалярными значениями, поэтому все, что вы можете сделать - это круги. Как я могу нарисовать эллиптические градиенты в CGContext
?
2 ответа
Вы должны иметь возможность масштабировать контекст и использовать CGContextDrawRadialGradient(). Если вы уменьшите масштаб, не должно быть никаких артефактов. Работает ли следующее?
CGContextRef context;
CGGradientRef gradient;
CGGradientDrawingOptions options;
CGPoint center;
CGFloat radiusX;
CGFloat radiusY;
CGFloat radius = MAX(radiusX, radiusY);
CGContextSaveGState(context);
// scale down by the smaller dimension, and translate so the center stays in place
if (radiusX < radiusY) {
CGContextTranslateCTM(context, center.x - (center.x * (radiusX / radiusY)), 0);
CGContextScaleCTM(context, radiusX / radiusY, 1.0);
}
else {
CGContextTranslateCTM(context, 0, center.y - (center.y * (radiusY / radiusX)));
CGContextScaleCTM(context, 1.0, radiusY / radiusX);
}
CGContextDrawRadialGradient(context, gradient, center, 0, center, radius, options);
CGContextRestoreGState(context);
Кстати, я думаю, что это примерно такое поведение, если вы установите type
собственностью CAGradientLayer
на недокументированную и личную ценность @"radial"
, Он использует начальную точку в качестве центра, а разность начальной точки и конечной точки для определения значений radiusX и radiusY (то есть конечная точка определяет угол ограничительной рамки градиента, а начальная точка - центр). Это имеет странное поведение, когда вы делаете начальную и конечную точки практически одинаковыми, поэтому, вероятно, там происходит больше, чем я догадывался (и, вероятно, почему Apple никогда не удосужилась обнародовать ее).
Там нет "королевской дороги". Это средство не является встроенным, поэтому вам придется рисовать каждый пиксель самостоятельно. (Вероятно, есть сторонние библиотеки, которые сделают это за вас.)
Единственное, о чем я могу подумать, это применить масштабное преобразование с неравными масштабными коэффициентами x и y к вашему контексту, прежде чем рисовать градиент. Это бы вытянуло его из круга и сделало бы его овальным.