여우처럼 주제 바꾸기🦊 환경광 기반💡 Angular 응용 프로그램에서
DISCLAIMER: This is a continuation of this article where I write about implementing a theme switch in an Angular App. If you haven't already read that, I recommend you to read this first.👇🏻
주제 전환을 실현합시다.🎨 모서리 재료 마당 같은 거.
Siddharth Ajmera 회사🇮🇳 각도・ 2020년 3월 19일・ 11분 읽기
That way you'll have more context of where I'm coming from.🙂
This article is intended for an audience with mixed experience levels. I've still added a TL;DR; below 👇🏻 as a precautionary measure, in case you're just interested in a specific section.
TL;박사
Enter: the
AmbientLightSensor
Web Interface 📡 AmbientLightSensor
Web Interface 왜 어두운 주제를 선택했습니까?🤷🏻♂️
So, as I mentioned in the , Dark Mode is awesome and low-lit ambiances are the best suited for #DarkMode.
Now changing themes in our App based on user interaction is OK. But we can take it to the next level by intelligently switching themes, based on the ambient lighting conditions that the user is in.
And that's exactly what we're going to do in this article.
언제 날이 어두워질지 확정하다⚡
Now you might think, how exactly do we determine that it's dark. Well, there's something called Illuminance that can help us do that.
Illuminance is a measure of the luminous flux spread over a given area.
One can think of luminous flux (which is measured in lumens BTW) as a measure of the total "amount" of visible light present, and the illuminance as a measure of the intensity of illumination on a surface.
따라서 간단하게 말하면 빛의 통량은 어둠도와 반비례한다.
참고로, 우리는 이 표를 사용하여 어둠의 정도를 확정할 것이다.
상기 표에서 판단하면 광통량이 10 또는 더 적으면 우리가 어두운 환경에 처해 있다고 안전하게 생각할 수 있다.하지만 이것은 내가 선택한 숫자일 뿐이다.당신의 취향에 따라 10-20(또는 50, 마음에 들면) 사이의 숫자를 마음대로 선택할 수 있습니다
좋아, 우리는 광통량에 따라 환경이 밝은지 어두운지 확정할 수 있어.그러나 우리는 어떻게 광통량을 확정합니까?🤔
환경 광센서웹 인터페이스 시작📡
This is a cool new interface from the Sensor APIs that returns the current light level or illuminance of the ambient light around the hosting device.
The
AmbientLightSensor
object has a property namedilluminance
on it, that returns the current light level in lux of the ambient light level around the hosting device.
It would only work on devices that have the ambient light sensor(hardware) on them(obviously). With the help of this AmbientLightSensor
interface, our browsers can access the data collected by Ambient Light Sensors on devices. Cool, isn't it? 🤩
What does that mean for us? Well, you can think of
illuminance
as the luminous flux incident on a surface.
Now we know how to get the illuminance
, and from the Illuminance Table 우리는 우리가 처한 환경이 어둠인지 광명인지 확인할 수 있다
따라서, 만약illuminance
<=10 (마찬가지로, 이 숫자는 전적으로 너에게 달려 있다), 그렇지 않으면
사용AmbientLightSensor
인터페이스 접근illuminance
은 매우 간단하며, MDN 문서의 this example에서 사용법이 언급되었습니다
하지만 이 인터페이스를 사용할 때 우리는 많은 다른 일에 주의해야 한다.하나하나 봅시다
피쳐 체크🕵🏻♂️:
This is to determine whether the browser that is running our App has the AmbientLightSensor
feature on it or not. To detect this, we can simply check:
if ("AmbientLightSensor" in window) {
// Yay! The Browser has what it takes
}
테두리 사례 처리:
Checking whether the browser supports a feature doesn't guarantee that everything will work as expected. There might be errors:
- While instantiation the sensor.
- While using it.
- When the user's permissions might be required to use the sensor.
- When the sensor type might not be supported by the device.
So all these scenarios would result in an error. So while using this interface, we'll have to cater to all these edge cases as well.
Now that we know what we're looking at, let's try to implement this in our App.
환경 광센서웹 인터페이스 사용
Reading the illuminance
and handling all these edge cases is the major task that we should delegate to a service. So let's implement a service in Angular that will handle all these things for us.
The only output that we're going to expect from this service is an Observable that either gives us the illuminance
or an error message that we could show to the user. So let's do this. I'll name this service AmbientLightSensorService
.
Also, since this service would also rely on the window
object, let's provide it as a value so that we could then inject it as a dependency in our AmbientLightSensorService
.
So in our AppModule
:
응용 프로그램.단원송전 시스템
...
import { AmbientLightSensorService } from "./ambient-light-sensor.service";
@NgModule({
...
providers: [
AmbientLightSensorService,
{
provide: Window,
useValue: window,
},
...
]
})
export class AppModule {}
우리는 또한 많은 메시지, 오류 유형, 센서 정책과 센서 이름 등을 처리할 것이다.우리도 그것들을 상수로 공개합시다:
흔했어상수송전 시스템
export const SENSOR_NAME = "AmbientLightSensor";
export const SENSOR_POLICY_NAME = "ambient-light-sensor";
export const ACCESS_DENIED = "denied";
export const THEME_OPTIONS_URL = "/assets/options.json";
export const THEME_BASE_PATH = "node_modules/@angular/material/prebuilt-themes";
export const STYLE_TO_SET = "theme";
export const DARK_THEME = "pink-bluegrey";
export const LIGHT_THEME = "deeppurple-amber";
export const ERROR_TYPES = {
SECURITY: "SecurityError",
REFERENCE: "ReferenceError",
NOT_ALLOWED: "NotAllowedError",
NOT_READABLE: "NotReadableError"
};
export const ERROR_MESSAGES = {
UNSUPPORTED_FEATURE: "Your browser doesn't support this feature",
BLOCKED_BY_FEATURE_POLICY:
"Sensor construction was blocked by a feature policy.",
NOT_SUPPORTED_BY_USER_AGENT: "Sensor is not supported by the User-Agent.",
PREMISSION_DENIED: "Permission to use the ambient light sensor is denied.",
CANNOT_CONNECT: "Cannot connect to the sensor."
};
내가 스스로 해석하는 방식으로 이 변수들을 명명하길 바란다
지금, 이 서비스를 실현합시다:
환경 광센서.서비스송전 시스템
import { ReplaySubject, Observable } from "rxjs";
import { Injectable } from "@angular/core";
import {
SENSOR_NAME,
SENSOR_POLICY_NAME,
ACCESS_DENIED,
ERROR_TYPES,
ERROR_MESSAGES
} from "./common.const";
@Injectable()
export class AmbientLightSensorService {
private illuminance: ReplaySubject <number> = new ReplaySubject <number>(1);
illuminance$: Observable<number> = this.illuminance.asObservable();
constructor(private window: Window) {
try {
if (SENSOR_NAME in window) {
this.startReading();
} else {
this.illuminance.error(ERROR_MESSAGES.UNSUPPORTED_FEATURE);
}
} catch (error) {
// Handle construction errors.
if (error.name === ERROR_TYPES.SECURITY) {
this.illuminance.error(ERROR_MESSAGES.BLOCKED_BY_FEATURE_POLICY);
} else if (error.name === ERROR_TYPES.REFERENCE) {
this.illuminance.error(ERROR_MESSAGES.NOT_SUPPORTED_BY_USER_AGENT);
} else {
this.illuminance.error(`${error.name}: ${error.message}`);
}
}
}
private startReading() {
const sensor = new AmbientLightSensor();
sensor.onreading = () => this.illuminance.next(sensor.illuminance);
sensor.onerror = async event => {
// Handle runtime errors.
if (event.error.name === ERROR_TYPES.NOT_ALLOWED) {
// Branch to code for requesting permission.
const result = await navigator.permissions.query({
name: SENSOR_POLICY_NAME
});
if (result.state === ACCESS_DENIED) {
this.illuminance.error(ERROR_MESSAGES.PREMISSION_DENIED);
return;
}
this.startReading();
} else if (event.error.name === ERROR_TYPES.NOT_READABLE) {
this.illuminance.error(ERROR_MESSAGES.CANNOT_CONNECT);
}
};
sensor.start();
}
}
우리가 지난 절에서 토론한 모든 변두리 상황을 만족시켜야 한다
기본적으로, 우리는illuminance
ReplaySubject<number>
illuminance$
"왜 aObservable<number>
입니까?"물어볼 수도 있어.우리는 초기값이 없기 때문에 그것으로 대체하는 것이 더 의미가 있다
현재, 우리는 호출ReplaySubject<number>(1)
방법을 통해 새로운 lux값을 아래로 밀어낸다BehaviorSubject<number>(null)
illuminance
.오류 상황에 대해 우리는 ReplaySubject
방법으로 오류를 제거합니다
방법 이름과 오류 메시지 이름도 쉽게 설명할 수 있습니다.만약 내가 상세하게 논술할 수 있도록 아래에 평론을 발표해 주십시오
현재 서비스가 준비되었습니다. 이 서비스를 의존항으로 주입하여 next
error
HeaderComponent
을 이용하여 lux값(또는 오류 메시지)에 접근할 수 있습니다
조도
import { Component, OnDestroy, OnInit } from "@angular/core";
import { MatSnackBar } from "@angular/material/snack-bar";
import { Observable, Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import { AmbientLightSensorService } from "../ambient-light-sensor.service";
import { DARK_THEME, LIGHT_THEME } from "../common.const";
import { Option } from "../option.model";
import { ThemeService } from "../theme.service";
@Component({
selector: "app-header",
templateUrl: "./header.component.html",
styleUrls: ["./header.component.css"]
})
export class HeaderComponent implements OnInit, OnDestroy {
options$: Observable<Array<Option>> = this.themeService.getThemeOptions();
private unsubscribe$ = new Subject<void>();
constructor(
private readonly themeService: ThemeService,
private readonly alsService: AmbientLightSensorService,
private readonly snackBar: MatSnackBar
) {}
ngOnInit() {
this.themeService.setTheme(DARK_THEME);
this.alsService.illuminance$
.pipe(takeUntil(this.unsubscribe$))
.subscribe(
illuminance => {
illuminance <= 10
? this.themeService.setTheme(DARK_THEME)
: this.themeService.setTheme(LIGHT_THEME);
},
error => this.showMessage(error)
);
}
themeChangeHandler(themeToSet) {
this.themeService.setTheme(themeToSet);
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
private showMessage(messageToShow) {
this.snackBar.open(messageToShow, "OK", {
duration: 4000
});
}
}
보시다시피:
- 우리는 현재
Observable
의존항으로 주입할 것이다. - 생명주기 연결에서 우리
header.component.ts
는AmbientLightSensorService
에 연결된다.여기서부터:- 사용
ngOnInit
값 호출이 성공적으로 리셋되었습니다.여기에서 우리는subscribe
값을 검사합니다.- 만약
Observable
이라면 우리는illuminance
를 설정합니다. - 만약
illuminance
이라면 우리는<= 10
를 설정합니다.
- 만약
-
DARK_THEME
메시지 호출 오류 리셋을 사용합니다.그곳에서 우리는 분식집을 표시하기 위해> 10
방법을 사용하기만 하면 된다.
- 사용
그 밖에 이번에 우리는 LIGHT_THEME
을 error
로 업그레이드했기 때문에, 우리는 어떤 메모리 유출도 피하기 위해 명확한 일을 해야 한다.이를 위해 showMessage
연산자를 사용하여 설명합니다
Read more about this approach in this article on AngularInDepth by Tomas Trajan
이렇게.우리의 subscribe
주제 전환이 이미 준비되었다.테스트를 해볼게요
시도해 보다🧪
Before we do that, there's a caveat. And it has something to do with browser support.
위에서 보듯이 브라우저 지원은 아직 좋지 않습니다.하지만 우리는 적어도 세계 최고의 브라우저에서 테스트를 해야 한다
이를 위해, 우리는 우선 하나의 표지판을 사용해야 한다:
그래서 나는 네비게이션Observable
을 하고 핸드폰에 그것을 사용할 것이다. (내 노트북에는 환경광 센서가 없다.)그리고 핸드폰에 있는 브라우저를 다시 켤게요
이제 테스트를 해볼게요:
마지막 코드는:
다음 단계👣
As of now, there's a slight issue in the App. What if the user doesn't want to change the theme automagically, based on the lighting conditions? We can add in a simple fix as a settings/preference menu asking to turn this behavior ON/OFF and switch the theme only when the behavior is turned ON.
Give it a try and implement the Preference/Settings Menu and then only switch the theme if the user has switched this auto-theme-switch behavior on.
폐막사🎉
Awwww! You're still here? Thanks for sticking around. I hope you liked it.
I’m extremely grateful to , and for taking the time to proofread it and providing all the constructive feedback in making this article better.
I hope this article has taught you something new related to Angular and Web in general. If it did, hit that 🧡/🦄 icon, and add it to your reading list(🔖). Also, share this article with your friends who are new to Angular/Web and want to achieve something similar.
Please stay tuned while I work on uploading a video version of this article. 📺
Icon Courtesy: Angular MaterialAngularIO출판사|CSSNoun프로젝트의monkik|Light sensorNoun프로젝트의Adnen Kadri
다음까지.👋🏻
Reference
이 문제에 관하여(여우처럼 주제 바꾸기🦊 환경광 기반💡 Angular 응용 프로그램에서), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/angular/switch-themes-like-a-fox-based-on-ambient-light-in-your-angular-apps-nk9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)