Иногда хочется запилить своими руками что-то интересное и немного даже полезное, но вот из-за того что я не программист (просто любитель), то приходится делать это своим странным способом с использованием некоторых костылей. Сегодня речь идет о том, как я сделал для себя виджет курса обмена валют на рабочий стол андроида.
Так как писать свой виджет это не просто так (в обычном блокноте это не сделать): нужна андроид студия, которая жрет ресурсов хренову кучу, да еще и нужно уметь в ней работать и программировать, то решено было поискать что-то готовое в плей маркете. Там удалось найти хорошую программу - Web Image Widget - программа просто выводит на рабочий стол картинку из интернета, по адресу задаваемому в настройках, и может масштабировать и менять размер виджета как душе угодно. Мне понравилось то, что нужная инфа может уместить лишь в одну ячейку:
Как видно на скрине, просто картинка с впечатанными в нее данными по курсам валют - удобно не так ли? Дважды щелкнул по картинке и данные обновились.
Теперь напишу как я это сделал. Как уже говорилось ранее, не обошлось без костылей, и обычным пользователям этот способ не совсем уж подходит, потому что для его реализации нужен хостинг с поддержкой PHP. У меня есть свой сайт, потому создать новый документ там не проблема, да и к тому же мне стало интересно можно ли с помощью PHP генерировать картинку с текстом. Оказалось что можно и делается это очень просто и легко.
За основу взял статью по функции https://www.php.net/manual/ru/function.imagettftext.php Первый пример в этой статье объясняет как пользоваться этой функцией, и что для чего нужно.
Первая строка у меня без изменения, а нужна для того чтобы страница возвращала именно картинку по запросу, а не непонятный набор байт:
header('Content-Type: image/png');
Теперь чтобы добавить универсальности мы добавим поддержку распознавания запрашиваемых валют: нужные нам валюты мы будем вбивать в адрес через запятую, таким образом адрес нашей картинки будет иметь такой вид https://yoursite.com/kurs.php?show=usd,eur,kzt ,а чтобы это сделать мы просто создаем массив $currences, куда помещаем все аргументы строки GET запроса, разделенные запятыми (то бишь аргументы usd,eur,kzt)
$currences = explode(",", $_GET["show"]);
и сразу же посчитаем сколько строк нам нужно выводить
$raws = count($currences);
На основе полученного количества строк, вычисляем разрешение картинки по вертикали, и рисуем соответствующих размеров и цветов прямоугольники
$font = 'ofont.ru_a_RubricaXtCn.ttf'; // шрифт текста. Если не указать картинка не сгенерируется
$y = $raws*70; //количество точек по вертикали
$im = imagecreatetruecolor(200, $y); //создаем картинку с конкретным разрешением
// Создание цветов
$bg = imagecolorallocate($im, 0, 0, 0); //цвет фона черный
$tc = imagecolorallocate($im, 100, 255,0); //цвет текста зеленыйimagefilledrectangle($im, 0, 0, 200, $y, $bg); //заливаем картинку цветом фона В конце файла делаем отрисовку изображения. Если в функции imagepng в скобках через запятую указать имя файла, то в заданной папке появится картинка с этим именем, и тогда забирать ее можно будет по конкретному адресу. Но проблема в том, что тогда придется ставить какой-то планировщик, который бы в определенное время генерировал бы картинку в соответствии с запрашиваемым им набором валют.
imagettftext($im, 40, 0, 5, 47, $tc, $font, $text);
imagepng($im);
imagedestroy($im);
Мы видим что в функции рисования есть переменная $text в которой содержатся наш текст с описанием валют и значением, а это значит что нам нужно получить актуальные данные с сервера курса валют и добавить их в переменную text. Вообще есть официальный сайт с курсами валют, но он отдает эти данные в формате xml, в котором чуть сложнее для меня автоматизировать процесс сбора нужных мне данных. Благо есть специальное зеркало этого сайта, откуда можно забрать курсы всех валют в формате JSON и выбрать из них те что нужны именно нам -для меня это оказалось вполне посильной задачей. Итак, в первую очередь создаем запрос :
function curlRequest($url)
{
$myCurl = curl_init();
curl_setopt_array($myCurl, array(
CURLOPT_URL => $url,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true,
));
$response = curl_exec($myCurl);
curl_close($myCurl);
return $response;
}
$url = 'http://www.cbr-xml-daily.ru/daily_json.js';
$contents = curlRequest($url);
Функция curlRequest($url) запрашивает текущий курс (пока еще все валюты что вообще есть) и помещает все это в $contents. Теперь мы это дело расшифруем
$data = json_decode($contents, true);
Ну а дальше идет самое сложное. В data теперь лежит расшифрованная строка json, но нам нужно пройтись по всем валютам, поэтому создаем массив $valutes куда помещаются массивы валют ($data[Valute]). Фишка в том что data это массив массивов, поэтому чтобы проверять значения CharCode каждой валюты, нужно делать именно так. Как уже говорилось выше, у нас есть массив валют, которые мы получили через GET и теперь пробегаясь по массиву Valutes мы ищем наши валюты, которые совпадают с CharCode ( strtoupper делает буквы заглавными)
$valutes = $data['Valute'];
$text='';
foreach ($valutes as $item) {
for ($i=0; $i<count($currences); $i++) {
if ($item['CharCode'] == strtoupper($currences[$i])) {
$val = ($item['Nominal']>1) ? round($item['Nominal']/$item['Value'],2) : round($item['Value'],2);
$char= ($item['Nominal']>1) ? $item['CharCode'].'*':$item['CharCode'];
$text = $text.$char.' '.$val.PHP_EOL;
}
}
}
Если найдено совпадение, то берем значение курса обмена, причем оно берется то что есть, если номинал равен 1, а вот если номинал больше 1, то вычисляем курс разделив номинал на значение, а к символьному обозначению добавляем звездочку. Мне кажется так удобнее считать, когда 5,66 тенге равны 1 рублю, а не когда 1 тенге равна 0,1766 рублей. Ну потом все это дело добавляем в переменную text, которая потом рисуем на картинке. .PHP_EOL - это перенос строки.
Целиком код выглядит так:
<?php
header('Content-Type: image/png');
//putenv('GDFONTPATH='.realpath('.'));
$font = 'ofont.ru_a_RubricaXtCn.ttf';
// Создание изображения
$currences = explode(",", $_GET["show"]);
$raws = count($currences);
$y = $raws*70;
$im = imagecreatetruecolor(200, $y);
// Создание цветов
$bg = imagecolorallocate($im, 0, 0, 0);
$tc = imagecolorallocate($im, 100, 255,0);
imagefilledrectangle($im, 0, 0, 200, $y, $bg);
function curlRequest($url)
{
$myCurl = curl_init();
curl_setopt_array($myCurl, array(
CURLOPT_URL => $url,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true,
));
$response = curl_exec($myCurl);
curl_close($myCurl);
return $response;
}
$url = 'http://www.cbr-xml-daily.ru/daily_json.js';
$contents = curlRequest($url);
$data = json_decode($contents, true);
$valutes = $data['Valute'];
$text='';
foreach ($valutes as $item) {
for ($i=0; $i<count($currences); $i++) {
if ($item['CharCode'] == strtoupper($currences[$i])) {
$val = ($item['Nominal']>1) ? round($item['Nominal']/$item['Value'],2) : round($item['Value'],2);
$char= ($item['Nominal']>1) ? $item['CharCode'].'*':$item['CharCode'];
$text = $text.$char.' '.$val.PHP_EOL;
//$text=$char;
}
}
}
imagettftext($im, 40, 0, 5, 47, $tc, $font, $text);
imagepng($im);
imagedestroy($im);
?>
А вот аналогичный код, который генерирует на javascript страницу с аналогичным текстом
Комментариев нет:
Отправить комментарий