Вы можете использовать размеры продолжения A
и B
с np.newaxis/None
, чтобы ввести broadcasting
для векторизованного решения так же -
A[...,None]*B[:,None,:]
Объяснение: np.outer(np.transpose(A[i]), B[i])
в основном выполняет элементное умножение между столбчатой версией A[i]
и B[i]
. Вы повторяете это для всех строк в A
для сопоставления строк в B
. Обратите внимание, что np.transpose()
, похоже, не оказывает никакого влияния, поскольку np.outer
заботится о предполагаемых элементарных умножениях.
Я бы описал эти шаги в векторизованном языке и, таким образом, реализовать так:
A
и B
, чтобы сформировать фигуры 3D
для обоих из них, чтобы мы сохранили axis=0
и сохранили как axis=0
в обеих этих расширенных версиях. Таким образом, нам остается решать две последние оси. axis=1
из A в своей исходной 2D-версии на axis=1
в своем 3D
, тем самым создавая одномерное измерение в axis=2
для расширенной версии A
. 3D
A
должно совпадать с элементами из axis=1
в оригинальной 2D
версии B
, чтобы broadcasting
произошло. Таким образом, расширенная версия B
имела бы элементы из axis=1
в своей 2D-версии, которые были бы нажаты на axis=2
в ее версии 3D
, тем самым создавая одномерное измерение для axis=1
. Наконец, расширенные версии: A[...,None]
& amp; B[:,None,:]
, умножив, кто даст нам желаемый результат.
Я использую CAShapeLayer
для маскировки UIView
, устанавливая self.layer.mask
для этого слоя формы.
Чтобы анимировать маску всякий раз, когда изменяется размер представления, я переписал -setBounds:
, чтобы анимировать путь слоя маски, если границы изменяются во время анимации.
Вот как я это реализовал:
- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
CAPropertyAnimation *boundsAnimation = (CABasicAnimation *)[self.layer animationForKey:@"bounds"];
// update the mask
self.maskLayer.frame = self.layer.bounds;
// if the bounds change happens within an animation, also animate the mask path
if (!boundsAnimation) {
self.maskLayer.path = [self createMaskPath];
} else {
// copying the original animation allows us to keep all animation settings
CABasicAnimation *animation = [boundsAnimation copy];
animation.keyPath = @"path";
CGPathRef newPath = [self createMaskPath];
animation.fromValue = (id)self.maskLayer.path;
animation.toValue = (__bridge id)newPath;
self.maskLayer.path = newPath;
[self.maskLayer addAnimation:animation forKey:@"path"];
}
}
(Для примера self.maskLayer
установлено значение `self.layer.mask)
My -createMaskPath
вычисляет CGPathRef, который я используйте, чтобы замаскировать вид. Я также обновляю путь маски в -layoutSubviews
.
Чтобы анимировать изменение границ слоя маски UIView: подкласс UIView, и анимировать маску с помощью транзакции CAT - аналогично ответу Kekodas, но более общего:
@implementation UIMaskView
- (void) layoutSubviews {
[super layoutSubviews];
CAAnimation* animation = [self.layer animationForKey:@"bounds"];
if (animation) {
[CATransaction begin];
[CATransaction setAnimationDuration:animation.duration];
}
self.layer.mask.bounds = self.layer.bounds;
if (animation) {
[CATransaction commit];
}
}
@end
Я не смог найти никакого программного решения, поэтому я просто нарисовал изображение PNG с правильной формой и значениями альфа и использовал его вместо этого. Таким образом, мне не нужно использовать маску ...
Быстрый 3+ ответ, основанный на решении Кекоа :
let duration = 0.15 //match this to the value of the UIView.animate(withDuration:) call
CATransaction.begin()
CATransaction.setValue(duration, forKey: kCATransactionAnimationDuration)
myView.layer.mask.position = CGPoint(x: [new X], y: [new Y]) //just an example
CATransaction.commit()
Свойство маски CALayer не может быть анимировано, что объясняет вашу неудачу в этом направлении.
Зависит ли рисунок вашей маски от рамки / границ маски? (Не могли бы вы предоставить код?) Установлено ли для маски свойство needsDisplayOnBoundsChange?
Ура, Корин