Если вам нравится использовать стороннюю библиотеку, проверьте traex / RippleEffect . Это позволяет добавить эффект Ripple в ANY view с помощью всего нескольких строк кода. Вам просто нужно обернуть в вашем файле макета xml элемент, который вы хотите иметь эффект пульсации с контейнером com.andexert.library.RippleView
.
В качестве дополнительного бонуса он требует Min SDK 9, поэтому вы можете иметь согласованность дизайна в версиях ОС.
Вот пример, взятый из репликации библиотек GitHub:
Вы можете изменить цвет пульсации, добавив этот атрибут в элемент RippleView: app:rv_color="@color/my_fancy_ripple_color
Проблема в том, что событие FileReader onLoadEnd является асинхронным, поэтому оно не будет работать внутри функции карты.
Один из способов решения вашей проблемы - обернуть вашу функцию Обещанием, создать наблюдаемое из обещания с из и использовать оператор switchMap для сопоставления вашего наблюдаемый к новому от обещания.
Теперь, когда вы подпишетесь на полученную наблюдаемую информацию, она выдаст результат из FileReader. Если он отклоняется, вы можете получить ошибку с помощью второго параметра метода подписки.
import {from} from 'rxjs'
import {switchMap} from 'rxjs/operators'
transform(url: string, asBase64: boolean): Observable<any> {
return this.http
.get(url, {responseType: 'blob'})
.pipe(
switchMap(
val => from( // create the observable from a promise
new Promise((resolve, reject) => { //create a new Promise
if (!asBase64) {
resolve(this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val))) //resolve if base64
}
const reader = new FileReader();
reader.readAsDataURL(val);
reader.onloadend = () => resolve(reader.result); //resolve when it finishes to load the file
reader.onerror = () => reject(reader.error); //rejects if there was an error while reading the file
})
)
)
);
}
...
const file$ = transform(url, asBase64)
file$.subscribe(
(file) => console.log(file), // do stuff with the file here
(error) => console.log(error) // there was an error while reading the file
)
Хорошо, понял это в конце. Поэтому мне нужно было использовать mergeMap
на основе ответа, а при желании asBase64
создать новую наблюдаемую из события чтения файла onloadend
.
Но это также не сработало из-за этих строк (см. Код в моем исходном вопросе).
let reader = new FileReader();
let eventObservable = fromEvent(reader, 'onloadend').pipe(map(() => {
return reader.result;
}));
reader.readAsDataURL(data);
return eventObservable;
Проблема с подходом fromEvent состоит в том, что событие запускается только один раз, и в моем случае оно срабатывало до того, как мой шаблон Angular смог подписаться на наблюдаемое, решение состояло в том, чтобы использовать Subject
, не уверенный, если это идеально в этом случае, но мне кажется, что все в порядке.
transform(url: string, asBase64: boolean): Observable<any> {
return this.http
.get(url, {responseType: 'blob'})
.pipe(map(val =>
<any>(asBase64 ? val : this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val)))
)).pipe(mergeMap(data => {
if (!asBase64) {
return of(data)
} else {
let reader = new FileReader();
let subject = new Subject<any>();
reader.onloadend = () => {
subject.next(reader.result);
};
reader.readAsDataURL(data);
return subject;
}
}));
}