てぃぐれのプログラマwiki

ワクワクに従う

メモ化 APIのコール数を減らす

経緯

サーバーに画像を取りにいく場合、そのキーをDBからとりにいく。大量の同じ画像をとるのであれば、メモ化しておきたい。

ディクショナリー型

キーをディクショナリー型のキーにしておいて、キーがある場合は、APIを呼ばない。キーがない場合は、APIを呼ぶようにするとAPIのコール数を減らすことができる。

メモ化のいろんな方法を知りたい。というかディクショナリーの奥深さを噛み締めている。

 

AdvancedMarkerViewをBlazorでやりたいんですが【Blazor】

経緯

マーカーにhtmlを使いたいとずっと思っていた。ふと見るとgoogleがAdvancedMarkerViewというベータ版の機能を提供しているではないか。

以前だとこれを実現しようとするとRichMarkerと巷で言われているoverlayviewを派生させて無理やり?作っていた。しかし、今回、Googleが正式に提供してくれることで、本来のマーカーの利用しやすくなった。というかGoogleが提供してくれるようになった。

RichMarkerをたくさん描画すると圧倒的にマーカーより思いこともあり、AdvancedMakrerViewに期待できないかと思っている。

 

とりあえずJSでやってみる

Advanced Markers (beta)  |  Maps JavaScript API  |  Google Developers

できた。ソースはおいおい載せる。

 

Blazorでやってみる

ライブラリはここのを利用する

GitHub - rungwiroon/BlazorGoogleMaps: Blazor interop for GoogleMap library

しかし、AdvancedMarkerViewのライブラリはまだない。

頑張って自作する。

だがうまくいかない。 AdvancedMarkerViewを呼ぶことはできる。

しかし、contentのプロパティに値を渡すことができない。contentに値をセットしないとデフォルトで値が渡るのでマーカーの設置はできるのだ。

contentのプロパティはelement型なのだが、C#にそのようなプロパティはない?

ElementReferenceがあるじゃないかと思ったが、うまくいかない。

 

後記

githubのやり取りを見るとやはり、このライブラリを作ってくれというやりとりはあるようだが、2022/11/19現在では、まだ実装はされていない。作者も忙しいとのことだった。

AdvancedMarkerViewはクラスタリングに対応がまだできていない。Google側が提供をまだできていないといったほうが正しいだろう。頑張れば自作できるっぽい。

下記がyoutubeのコメントでgoogleが返信を返していた内容だ。

Announcing: Advanced Markers - YouTube

The js-markerclusterer utility library currently uses Marker class to construct and render the cluster icon, so it doesn't support the marker.AdvanceMarkerView class features. You can see a sample of the js-markerclusterer's default renderer implementation here: https://googlemaps.github.io/js-markerclusterer/classes/DefaultRenderer.html

 

誰か、elementをC#から渡して、AdvancedMarkerViewを使える方法を教えてください。

 

 

 

 

 

画像の縦横比をいい感じにする object-fit【css】

経緯

デザインで特定の枠に画像を収めたいというときはよくあるであろう。

縦固定でwidth100%にするのか、はたまたその逆か。どちらにせよ、どちらかに大きな値が来た場合くしゃってひしゃげてしまう。

 

大きいほうを基準に小さいほうをそろえる

何かの枠に収めたいとき、その枠を最大値としたい。そのため、その画像の大きいほうを最大値にしてあげて、小さいほうをその拡大した%に合わせてあげたい。

そうすることで、縦長が来ても、横長が来ても対応ができるのである。

これはレターボックスという映像技術らしい。

レターボックス (映像技術) - Wikipedia

 

 

CSSでの書き方

object-fit - CSS: カスケーディングスタイルシート | MDN

これを条件分岐みたいにCSSで書くのは難しそうだなあとおもっていたところ、object-fitというスタイルがあった。まさに、欲しかったものであり、しかも中央ぞろえにまでしてくれるというすぐれものである。

1段目が無理やり入れようとしたことでつぶれている画像であり、2段目の画像の縦横比が本来正しい。

1段目は縦横どちらかを固定しもう片方にautoをかけている。

2段目はobject-fit:contain;を利用している。

とても便利である。

 

 

コード

<div class="wrapper">
    <div class="container">
        <img class="img-size-w-auto"
    </div>
    <div class="container">
        <img class="img-size-h-auto"
    </div>
    <div class="container">
        <img class="img-size-w-auto"
    </div>
    <div class="container">
        <img class="img-size-h-auto"
    </div>
</div>
<div class="wrapper">
    <div class="container">
        <img class="img-size-fit"
    </div>
    <div class="container">
        <img class="img-size-fit"
    </div>
</div>
<style>
.wrapper{
    display: flex;
}    
.container{
    height: 500px;
    width: 500px;
    background-color: aqua;
    border:solid 5px crimson;
}
.img-size-w-auto{
    height: 500px;
    width: 100%;
}

.img-size-h-auto{
    height: 100%;
    width: 500px;
}
.img-size-fit{
    height:500px;
    width:500px;
    object-fit:contain;
}

</style>

 

 

 

 

 

ぐるぐる スピナーを出す方法【C# Blazor】

経緯

Webの処理の待機中にスピナーを出したい。

 

対処法

divの中身はbootstrapから頂いております。bootstrapのコンポーネントが入ってない人はそれらを記述する必要がindex.html等であります。

@page "/counter"


@if(IsWaiting)
{
    <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">Loading...</span>
    </div>    
}
boolのtrue falseで出す出さないをすることで、検索する時等につかうことができます。
@code {

    private bool IsWaiting = false;

    private async Task OnClick()
    {

        IsWaiting = true;

        try
        {
            await Task.Delay(3000,token);
        }finally
        {
            IsWaiting = false;            
        }
  }
}

?クエスチョンマークの使い方1 Null条件演算子【C#】

経緯

?マークのC#での使い方を押さえておきたい。それによりもっときれいなコードをかくことができるはずだ。

Null条件演算子

三項演算子

Null合体演算子

で使われる。今回はNull条件演算子を押さえたい。

 

 

エラーになるコード

nullがくるとFirst()で参照できなくてエラーになる

First()でエラーになるのはありがち

        IsWaiting = true;

        try
        {
            await Task.Delay(3000,token);
            string test = null;

            await Calling(test);
        }finally
        {
            IsWaiting = false;            
        }
    }

    List<CancellationTokenSource> _cancellationTokenSource = new();

    private async Task Calling(string test)
    {
        Console.WriteLine(test.First());        
    }
 
 

エラーにならないコード

        IsWaiting = true;

        try
        {
            await Task.Delay(3000,token);
            string test = null;

            await Calling(test);
        }finally
        {
            IsWaiting = false;            
        }
    }

    List<CancellationTokenSource> _cancellationTokenSource = new();

    private async Task Calling(string test)
    {
        Console.WriteLine(test?.First());        
    }
 

前回の処理を取り消して新しく処理したい【Blazor】

経緯

前回の処理を取り消して、新しく処理を開始したい。

チェックボックスなどのたくさんクリックして行いがちな処理をTask.Delayを使って、3秒間待って、何の入力もないのであれば、処理を行い、入力があれば、前回の処理を取り消して処理を行いたい。

そうすることで無駄にAPI(処理)を呼ぶことを少なくしたい。

 

CancellingTokenで分かったこと

CancellingTokenの使いかたが全然わからなくて、このソースと戦っていた。

【分かったこと】

・Tokenを渡して次の処理で、前回の処理を消す必要があるため、前回のインスタンスのキャンセルをする必要がある。

・Delayでキャンセルされた以降の処理は行われない

 

もっとキャンセルについて理解を深めたい

 

ソース blazorの環境(bootstrapのスピナーを利用している)

 
@page "/counter"


@if(IsWaiting)
{
    <div class="spinner-border text-primary" role="status">
        <span class="visually-hidden">Loading...</span>
    </div>    
}

<button style="width:1000px;height:25px;"
@onclick="( async () => await OnClick())" >push</button>

@code {

    private bool IsWaiting = false;

    private int Count = 0;

    private async Task OnClick()
    {
        _cancellationTokenSource.Add(new());
        var token = _cancellationTokenSource[Count].Token;

        if(IsWaiting)
        {
            _cancellationTokenSource[Count - 1].Cancel();
        }
        Count += 1;
        IsWaiting = true;

        try
        {
            await Task.Delay(3000,token);
            string test = "test";
            await Calling(test);                            
        }finally
        {
            IsWaiting = false;            
        }
    }

    List<CancellationTokenSource> _cancellationTokenSource = new();

    private async Task Calling(string test)
    {
        Console.WriteLine(test);        
    }
}