Отказ от ответственности: Это продолжение этой статьи, где я пишу о реализации тематического переключателя в угловом приложении. Если вы еще этого не читали, я рекомендую вам прочитать это первым.
Давайте реализуем тематический коммутатор 🎨, как угловой материал
Siddharth ajmera 🇮🇳 для угловых · 198,20 · 11 мин читать
Таким образом, у вас будет больше контекста, откуда я иду. 🙂
Эта статья предназначена для аудитории со смешанным уровнем опыта. Я все еще добавил TL; DR; Ниже 👇🏻 в качестве меры предосторожности, если вы просто заинтересованы в конкретном разделе.
TL; DR;
- Почему темная тема в темноте? 🤷 🏻♂️.
- Определение, когда это тьма
- Введите: веб-интерфейс AmbientLightsensor 📡
- Обнаружение функций 🕵🏻♂️.
- Обращение с краями
- Использование веб-интерфейса AmbientLightsensor
- Пробуя это
- Следующие шаги 👣.
- Закрытие заметки 🎉.
Начать, мы просто продолжим с одинаковое угловое приложение что мы построили в Последняя статья Отказ
Почему темная тема в темноте? 🤷 🏻♂️.
Итак, как я уже упоминал в предыдущей статье, Dark Mode – это потрясающие, а нижние достигающиеся, являются лучшими подходящими для #DarkMode.
Теперь изменяющие темы в нашем приложении на основе взаимодействия пользователя в порядке. Но мы можем принять его на следующий уровень, разумно переключающие темы, основанные на условиях окружающей среды, в которых используется пользователь.
И это именно то, что мы собираемся сделать в этой статье.
Определение, когда это темный ⚡.
Теперь вы можете подумать, как именно мы определяем, что это темно. Ну, есть что называется Освещенность Это может помочь нам сделать это.
По словам Википедия :
Соблюдение – это мера Световой поток распространяться по данной области.
Можно подумать о светящемся потоке (который измеряется в люменах BTW) в качестве меры общего «количества» видимого света, а также освещенности в качестве меры интенсивности освещения на поверхности.
” Таким образом, в более простых терминах светящийся поток обратно пропорционален темноту ».
Для некоторой ссылки мы будем использовать эту таблицу, чтобы определить тьму:
Судя по таблице выше, было бы безопасно рассмотреть, что если светлый поток – 10 или менее, мы в темной среде. Но это просто номер, который я выбрал. Не стесняйтесь выбирать число от 10 до 20 (или 50, если хотите) на основании ваших предпочтений.
Итак, мы можем определить, являются ли среда легкими или темными на основе светящегося потока. Но как мы определяем светящийся поток? 🤔
Введите: веб-интерфейс AmbientLightsensor 📡
Это прохладный новый интерфейс от Датчик API Это возвращает текущий уровень света или освещенности окружающей среды вокруг устройства хостинга.
AmbientLightsensor Объект имеет свойство имени освещенность На нем это возвращает текущий уровень света в Люкс уровня окружающей среды вокруг устройства хостинга.
Он будет работать только на устройствах, которые имеют датчик окружающего света (оборудование) на них (очевидно). С помощью этого AmbientLightsensor Интерфейс, наши браузеры могут получить доступ к данным, собранным датчиками окружающей среды на устройствах. Круто, не так ли? 🤩.
Что это значит для нас? Ну, вы можете думать о освещенность в качестве светового потока падающего на поверхности.
Теперь мы знаем, как получить освещенность и из Стол освещения Мы можем определить, является ли среда, в которой мы в темном или свете.
Итак, мы рассмотрим окружающую среду, чтобы быть темной, если освещенность (Опять же, это число полностью зависит от вас), свет иначе.
Используя AmbientLightsensor Интерфейс для доступа освещенность довольно просто, и использование упоминается в Этот пример на Docs MDN.
Но есть много других вещей, которые нам нужно позаботиться о том, чтобы использовать этот интерфейс. Давайте пройдемся через них один за другим.
Обнаружение функций 🕵🏻♂️:
Это должно определить, работает ли браузер, который работает наше приложение, имеет AmbientLightsensor функция на нем или нет. Чтобы обнаружить это, мы можем просто проверить:
if ("AmbientLightSensor" in window) {
// Yay! The Browser has what it takes
}
Обработка краевых чехлов:
Проверка, поддерживает ли браузер функцией, не гарантирует, что все будет работать должным образом. Там могут быть ошибки:
- Хотя призвать датчик.
- При использовании этого.
- Когда разрешения пользователя могут потребоваться использовать датчик.
- Когда тип датчика не может быть поддерживаться устройством.
Таким образом, все эти сценарии приведут к ошибке. Поэтому при использовании этого интерфейса нам придется также удовлетворить все эти эти кромки.
Теперь, когда мы знаем, на что мы смотрим, давайте попробуем реализовать это в нашем приложении.
Использование веб-интерфейса AmbientLightsensor
Чтение освещенность и обращение с всеми этими следующими случаями, являются основной задачей, которую мы должны делегировать на услугу. Итак, давайте реализуем услугу в угловом угловом углу, которая будет справиться со всеми этими вещами для нас.
Единственный выход, который мы собираемся ожидать от этой службы, является наблюдаемым, что либо дает нам освещенность или сообщение об ошибке, которое мы могли бы показать пользователю. Итак, давайте сделаем это. Я назову эту услугу AmbientLightsenssorservice .
Также, так как эта услуга также полагается на окно Объект, давайте предоставляем это как значение, чтобы мы могли ввести его как зависимость в нашем AmbientLightsenssorservice Отказ
Так в нашем AppModule :
app.module.ts.
...
import { AmbientLightSensorService } from "./ambient-light-sensor.service";
@NgModule({
...
providers: [
AmbientLightSensorService,
{
provide: Window,
useValue: window,
},
...
]
})
export class AppModule {}
Существует также много сообщений, типов ошибок, политика датчика и имя датчика и т. Д. Что мы собираемся иметь дело с. Итак, давайте также распределим их в качестве постоянных:
Common.const.ts.
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."
};
Надеюсь, я назвал эти переменные таким образом, чтобы они были объяснительными.
Теперь давайте реализуем эту услугу:
Ambient-Light-Sensor.service.ts
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 = new ReplaySubject (1);
illuminance$: Observable = 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();
}
}
Реализация обслуживает каждое краевое дело, которое мы обсуждали в предыдущем разделе.
В основном мы выставили освещенность Replaysubject <номер> Как Подсветка $ Наблюдаемый <номер> Отказ
«Почему a replaysubject ? «Вы можете спросить. Что ж, потому что у нас нет начальной ценности, и поэтому у него будет иметь больше смысла использовать это вместо использования Поведение ... Номер> (NULL) .
Теперь мы нажимаем новые значения люкс вниз по освещенность Replaysubject Призывая Следующий Метод на нем. И для случаев ошибок мы выдвигаем ошибку, используя Ошибка метод.
Имена методов и имена сообщений об ошибках довольно объясняют. Если что-то все еще не понятно, пожалуйста, прокомментируйте ниже, чтобы я мог сложить больше на нем.
И вот теперь, когда служба готова, мы можем ввести эту услугу как зависимость в нашем HeaderComponent и использовать Подсветка $ Наблюдаемый Чтобы получить доступ к значению LUX (или сообщение об ошибке).
header.component.ts.
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> = this.themeService.getThemeOptions();
private unsubscribe$ = new Subject();
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
});
}
}
Так как вы можете заметить:
- Теперь мы вводили
AmbientLightsenssorserviceкак зависимость. В
NgoninitКрюк жизненного цикла, мыПодписатьсякНаблюдаемыйОтказ Отсюда:Успех обратного вызова вызывается с
освещенностьстоимость. Здесь мы проверяемосвещенностьстоимость:- Если это
<= 10Затем мы установилиDark_ThemeОтказ - Если это
> 10Затем мы установилиLight_themeОтказ
- Если это
- Ошибка обратного вызова вызывается с
Ошибкасообщение. Оттуда мы просто называемShowMessageСпособ показать закусочную.
Также, так как мы Подписаться к Наблюдаемый На этот раз вокруг, мы также придется явно сделать что-то, чтобы избежать утечек памяти. Чтобы сделать это, мы идем декларативно, используя доставка оператор.
Узнайте больше об этом подходе в Эта статья на Angularindepth по Tomas Trajan.
Вот и все. Наше Датчик освещенности Тематический коммутатор теперь готов. Давайте проверим это.
Пробуя это
Прежде чем мы сделаем это, есть предостережение. И это есть что связано с поддержкой браузера.
Как вы можете видеть выше, поддержка браузера не так отлично в данный момент. Но мы, по крайней мере, проверим это на лучшем браузере в мире (Ahem Chrome Ahem).
Для этого мы сначала придется включить флаг:
Так что я перейду на Chrome://Флаги/# Включить-универсальный сенсор - Extra-Classes и включить его на моем телефоне (мой ноутбук не имеет датчика окружающего света на нем). И тогда я перезагрузим браузер на моем телефоне.
Давайте теперь проверим эту вещь:
И вот последний код:
Следующие шаги 👣.
На данный момент в приложении появляется небольшая проблема. Что если пользователь не хочет менять тему, автоматически, основываясь на условиях освещения? Мы можем добавить в простой фиксировании в качестве меню «Настройки/предпочтения», просимая включение/выключение этого поведения и переключить тему только тогда, когда поведение включено.
Дайте ему попробуйте и реализуйте меню «Предпочтения/настройки», а затем только переключите тему, если пользователь переключил это поведение «Автоматическое переключение».
Закрытие заметки 🎉.
Awwww! Ты все еще здесь? Спасибо за прилипание. Я надеюсь, тебе понравилось это.
Я чрезвычайно благодарен Мартине Краусу, и Раджата Бадьятья за то, что набрал время, чтобы преодолеть его и предоставить всю конструктивную обратную связь в создании этой статьи лучше.
Я надеюсь, что эта статья научила вас что-то новое, связанное с угловым и сетью в целом. Если это сделало, нажмите это 🧡/🦄 значок и добавьте его в список чтения (🔖). Кроме того, поделитесь этой статьей со своими друзьями, которые новые для угнта/в Интернете, и хотят достичь чего-то подобного.
Пожалуйста, остайтесь настроенными, пока я работаю над загрузкой видео версии этой статьи. 📺
Значок вежливости: Угловой материал Angulario Press Kit | CSS от моника из существительного проекта | Датчик света Аднен Кадри из существительного проекта
До следующего раза тогда. 👋🏻.
Оригинал: “https://dev.to/angular/switch-themes-like-a-fox-based-on-ambient-light-in-your-angular-apps-nk9”